From a48c08774ce768031863370c8bb6450ce17b699f Mon Sep 17 00:00:00 2001 From: Bartek Igielski Date: Sun, 9 Sep 2018 16:04:28 +0200 Subject: [PATCH 001/603] Loader replaced with actual product photo to visualy speedup loading --- .../templates/product/view/gallery.phtml | 30 +++++-------------- lib/web/mage/gallery/gallery.less | 10 +++---- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml index 1bfa30478df8a..79714d5bf9035 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml @@ -12,32 +12,16 @@ * @var $block \Magento\Catalog\Block\Product\View\Gallery */ ?> + +getGalleryImages()->toArray()['items'] ?> + - - #is'; + $content = preg_replace_callback( + $pattern, + function ($matchPart) use (&$script) { + $script[] = $matchPart[0]; + return ''; + }, + $content + ); + $subject->setContent( + str_replace(' + + + From 9b324e804c58ed2b05c9646bcd7c781ecf113edc Mon Sep 17 00:00:00 2001 From: Denis Kopylov Date: Wed, 27 Mar 2019 22:29:48 +0300 Subject: [PATCH 239/603] [BUG] Fix gallery event observer --- lib/web/mage/gallery/gallery.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/mage/gallery/gallery.js b/lib/web/mage/gallery/gallery.js index 15c3d01cf2be3..be78856b21fcd 100644 --- a/lib/web/mage/gallery/gallery.js +++ b/lib/web/mage/gallery/gallery.js @@ -141,7 +141,7 @@ define([ this.setupBreakpoints(); this.initFullscreenSettings(); - this.settings.$element.on('mouseup', '.fotorama__stage__frame', function () { + this.settings.$element.on('click', '.fotorama__stage__frame', function () { if ( !$(this).parents('.fotorama__shadows--left, .fotorama__shadows--right').length && !$(this).hasClass('fotorama-video-container') From 938dd362d47844045488f263b776bdb821fdb55c Mon Sep 17 00:00:00 2001 From: Denis Kopylov Date: Wed, 27 Mar 2019 22:46:32 +0300 Subject: [PATCH 240/603] [Module Rule] Revert es6 variable diclarations --- app/code/Magento/Rule/view/adminhtml/web/rules.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Rule/view/adminhtml/web/rules.js b/app/code/Magento/Rule/view/adminhtml/web/rules.js index 202337c39da35..a15caa08cc0ae 100644 --- a/app/code/Magento/Rule/view/adminhtml/web/rules.js +++ b/app/code/Magento/Rule/view/adminhtml/web/rules.js @@ -13,6 +13,7 @@ define([ 'mage/translate', 'prototype' ], function (jQuery) { + 'use strict'; var VarienRulesForm = new Class.create(); @@ -299,14 +300,14 @@ define([ }, changeVisibilityForValueRuleParam: function(elem) { - let parsedElementId = elem.id.split('__'); - if (parsedElementId[2] != 'operator') { + var parsedElementId = elem.id.split('__'); + if (parsedElementId[2] !== 'operator') { return false; } - let valueElement = jQuery('#' + parsedElementId[0] + '__' + parsedElementId[1] + '__value'); + var valueElement = jQuery('#' + parsedElementId[0] + '__' + parsedElementId[1] + '__value'); - if(elem.value == '<=>') { + if(elem.value === '<=>') { valueElement.closest('.rule-param').hide(); } else { valueElement.closest('.rule-param').show(); From a04154b10f2b62611722064085ede8cf03c50983 Mon Sep 17 00:00:00 2001 From: Leandry Date: Wed, 27 Mar 2019 22:49:58 +0200 Subject: [PATCH 241/603] Add suggested changes --- ...frontCustomerAccountInformationSection.xml | 16 +++++++ .../Mftf/Test/CaptchaEditCustomerTest.xml | 48 +++++++++++-------- ...orefrontCustomerChangeEmailActionGroup.xml | 27 +++++++++++ .../Mftf/Page/StorefrontCustomerEditPage.xml | 14 ++++++ ...frontCustomerAccountInformationSection.xml | 8 ++-- .../StorefrontCustomerAccountMainSection.xml | 1 + .../Test/TestCase/CaptchaEditCustomerTest.xml | 1 + 7 files changed, 89 insertions(+), 26 deletions(-) create mode 100644 app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerChangeEmailActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerEditPage.xml diff --git a/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml new file mode 100644 index 0000000000000..6a274601e69ed --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml @@ -0,0 +1,16 @@ + + + + +
+ + + +
+
\ No newline at end of file diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml index 646c9af3ba55f..ad126617611c6 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml @@ -35,39 +35,45 @@ - + - - - - + + + + + + - - - - + + + + + + - - - - + + + + + + - - - + + + - - - - + + + + - + diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerChangeEmailActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerChangeEmailActionGroup.xml new file mode 100644 index 0000000000000..6500d7800b6a1 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerChangeEmailActionGroup.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerEditPage.xml b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerEditPage.xml new file mode 100644 index 0000000000000..d4cf90dde08ff --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerEditPage.xml @@ -0,0 +1,14 @@ + + + + + +
+ + \ No newline at end of file diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml index e93985b4f469b..8a633ec5bc271 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml @@ -11,16 +11,14 @@
- - + + - - - +
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountMainSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountMainSection.xml index 3a4329969ae2b..c00b54b3964da 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountMainSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountMainSection.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
+
diff --git a/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaEditCustomerTest.xml b/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaEditCustomerTest.xml index 12b9808adb9e0..0c0e06d63b6c9 100644 --- a/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaEditCustomerTest.xml +++ b/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaEditCustomerTest.xml @@ -14,6 +14,7 @@ 3 111 captcha_storefront_user_edit_failures_number, customer_max_login_failures_number + mftf_migrated:yes From aa4a7a53ef7c9403039c7e4144c8aef909eb98c3 Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin Date: Thu, 28 Mar 2019 09:15:33 +0200 Subject: [PATCH 242/603] MAGETWO-98886: Gift Card Accounts: expiration date subtracts one day --- .../Framework/Data/Form/Element/Date.php | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Date.php b/lib/internal/Magento/Framework/Data/Form/Element/Date.php index 897617e560be5..28e9a18337c68 100644 --- a/lib/internal/Magento/Framework/Data/Form/Element/Date.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Date.php @@ -53,6 +53,19 @@ public function __construct( } } + /** + * Check if a string is a date value + * + * @param string $value + * @return bool + */ + private function isDate(string $value): bool + { + $date = date_parse($value); + + return !empty($date['year']) && !empty($date['month']) && !empty($date['day']); + } + /** * If script executes on x64 system, converts large numeric values to timestamp limit * @@ -85,13 +98,13 @@ public function setValue($value) $this->_value = $value; return $this; } - try { if (preg_match('/^[0-9]+$/', $value)) { $this->_value = (new \DateTime())->setTimestamp($this->_toTimestamp($value)); + } else if (is_string($value) && $this->isDate($value)) { + $this->_value = new \DateTime($value, new \DateTimeZone($this->localeDate->getConfigTimezone())); } else { - $this->_value = new \DateTime($value); - $this->_value->setTimezone(new \DateTimeZone($this->localeDate->getConfigTimezone())); + $this->_value = ''; } } catch (\Exception $e) { $this->_value = ''; From 1fe977a11c238b19e6f79342bed637bc7941bea8 Mon Sep 17 00:00:00 2001 From: RomanKis Date: Thu, 28 Mar 2019 11:43:58 +0200 Subject: [PATCH 243/603] #21998 Magento/ImportExport/Model/Import has _coreConfig declared dynamically --- app/code/Magento/ImportExport/Model/Import.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/code/Magento/ImportExport/Model/Import.php b/app/code/Magento/ImportExport/Model/Import.php index d115aea7f2ff9..2a4d6904b11b5 100644 --- a/app/code/Magento/ImportExport/Model/Import.php +++ b/app/code/Magento/ImportExport/Model/Import.php @@ -126,6 +126,11 @@ class Import extends \Magento\ImportExport\Model\AbstractModel */ protected $_importExportData = null; + /** + * @var \Magento\Framework\App\Config\ScopeConfigInterface + */ + private $_coreConfig; + /** * @var \Magento\ImportExport\Model\Import\ConfigInterface */ From 2d8404d59dafd97c4881dfb1529deb6ce3d8e0f6 Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn Date: Thu, 28 Mar 2019 12:04:25 +0200 Subject: [PATCH 244/603] MAGETWO-98680: Cart Price Rule code is absent on "view Order/Invoice" Admin page if had been used for Free Shipping --- app/code/Magento/Sales/Block/Adminhtml/Totals.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/Totals.php b/app/code/Magento/Sales/Block/Adminhtml/Totals.php index f26df0946168a..ccc05a54676d9 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Totals.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Totals.php @@ -75,7 +75,7 @@ protected function _initTotals() $this->getSource()->getShippingDescription()) ) { $shippingLabel = __('Shipping & Handling'); - if ($this->isHasFreeShipping($this->getSource()) && $this->getSource()->getDiscountDescription()) { + if ($this->isHasFreeShipping($this->getOrder()) && $this->getSource()->getDiscountDescription()) { $shippingLabel .= sprintf(' (%s)', $this->getSource()->getDiscountDescription()); } $this->_totals['shipping'] = new \Magento\Framework\DataObject( From 9e6f56bee5b354981a7a45bac26620f598d9cd72 Mon Sep 17 00:00:00 2001 From: Vishal Sutariya Date: Thu, 28 Mar 2019 15:35:46 +0530 Subject: [PATCH 245/603] Removed unwanted interface implementation --- .../Backend/Controller/Adminhtml/Dashboard/ProductsViewed.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/Backend/Controller/Adminhtml/Dashboard/ProductsViewed.php b/app/code/Magento/Backend/Controller/Adminhtml/Dashboard/ProductsViewed.php index 0de1111ffa722..216c730ccccc0 100644 --- a/app/code/Magento/Backend/Controller/Adminhtml/Dashboard/ProductsViewed.php +++ b/app/code/Magento/Backend/Controller/Adminhtml/Dashboard/ProductsViewed.php @@ -6,12 +6,10 @@ */ namespace Magento\Backend\Controller\Adminhtml\Dashboard; -use Magento\Framework\App\Action\HttpGetActionInterface; - /** * Get most viewed products controller. */ -class ProductsViewed extends AjaxBlock implements HttpGetActionInterface +class ProductsViewed extends AjaxBlock { /** * Gets most viewed products list From 975872e4a5cd8b3b8642e22ff8260e5ddb830f74 Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn Date: Thu, 28 Mar 2019 15:09:29 +0200 Subject: [PATCH 246/603] MAGETWO-98680: Cart Price Rule code is absent on "view Order/Invoice" Admin page if had been used for Free Shipping --- .../Magento/Sales/Block/Adminhtml/Totals.php | 14 ++++++-------- .../Magento/Sales/Block/Adminhtml/TotalsTest.php | 16 +++++++++------- .../order_with_free_shipping_by_coupon.php | 1 + 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/Totals.php b/app/code/Magento/Sales/Block/Adminhtml/Totals.php index ccc05a54676d9..8172a3c0db4ad 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Totals.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Totals.php @@ -9,8 +9,6 @@ /** * Adminhtml sales totals block - * - * @package Magento\Sales\Block\Adminhtml */ class Totals extends \Magento\Sales\Block\Order\Totals { @@ -75,7 +73,7 @@ protected function _initTotals() $this->getSource()->getShippingDescription()) ) { $shippingLabel = __('Shipping & Handling'); - if ($this->isHasFreeShipping($this->getOrder()) && $this->getSource()->getDiscountDescription()) { + if ($this->isFreeShipping($this->getOrder()) && $this->getSource()->getDiscountDescription()) { $shippingLabel .= sprintf(' (%s)', $this->getSource()->getDiscountDescription()); } $this->_totals['shipping'] = new \Magento\Framework\DataObject( @@ -127,16 +125,16 @@ protected function _initTotals() * @param Order $order * @return bool */ - private function isHasFreeShipping(Order $order): bool + private function isFreeShipping(Order $order): bool { - $isActive = false; + $isFreeShipping = false; foreach ($order->getItems() as $orderItem) { - if ($orderItem->getFreeShipping() === '1') { - $isActive = true; + if ($orderItem->getFreeShipping() == '1') { + $isFreeShipping = true; break; } } - return $isActive; + return $isFreeShipping; } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/TotalsTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/TotalsTest.php index 091b8e3f2b72c..1125fc1730718 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/TotalsTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/TotalsTest.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Sales\Block\Adminhtml; use Magento\Framework\View\LayoutInterface; @@ -15,10 +17,10 @@ class TotalsTest extends \Magento\TestFramework\TestCase\AbstractBackendController { /** @var LayoutInterface */ - protected $_layout; + private $layout; /** @var Totals */ - protected $_block; + private $block; /** @var OrderFactory */ private $orderFactory; @@ -29,8 +31,8 @@ class TotalsTest extends \Magento\TestFramework\TestCase\AbstractBackendControll protected function setUp() { parent::setUp(); - $this->_layout = $this->_objectManager->get(LayoutInterface::class); - $this->_block = $this->_layout->createBlock(Totals::class, 'totals_block'); + $this->layout = $this->_objectManager->get(LayoutInterface::class); + $this->block = $this->layout->createBlock(Totals::class, 'totals_block'); $this->orderFactory = $this->_objectManager->get(OrderFactory::class); } @@ -43,10 +45,10 @@ public function testShowShippingCoupon() $order = $this->orderFactory->create(); $order->loadByIncrementId('100000001'); - $this->_block->setOrder($order); - $this->_block->toHtml(); + $this->block->setOrder($order); + $this->block->toHtml(); - $shippingTotal = $this->_block->getTotal('shipping'); + $shippingTotal = $this->block->getTotal('shipping'); $this->assertNotFalse($shippingTotal, 'Shipping method is absent on the total\'s block.'); $this->assertContains( '1234567890', diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_free_shipping_by_coupon.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_free_shipping_by_coupon.php index 04e39ae3e462c..57ccffadaa4d0 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_free_shipping_by_coupon.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_free_shipping_by_coupon.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Model\Order; From f826017acfb81d549d5eaada07a0081ddc2498c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20K=C3=B6cke?= Date: Thu, 28 Mar 2019 14:55:05 +0100 Subject: [PATCH 247/603] Correct bug 21993 config:set not storing scoped values --- .../Config/Console/Command/ConfigSet/DefaultProcessor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Config/Console/Command/ConfigSet/DefaultProcessor.php b/app/code/Magento/Config/Console/Command/ConfigSet/DefaultProcessor.php index 86ae1f96749df..c622a48b7f2c8 100644 --- a/app/code/Magento/Config/Console/Command/ConfigSet/DefaultProcessor.php +++ b/app/code/Magento/Config/Console/Command/ConfigSet/DefaultProcessor.php @@ -90,10 +90,10 @@ public function process($path, $value, $scope, $scopeCode) } try { - $config = $this->configFactory->create([ + $config = $this->configFactory->create(['data' => [ 'scope' => $scope, 'scope_code' => $scopeCode, - ]); + ]]); $config->setDataByPath($path, $value); $config->save(); } catch (\Exception $exception) { From 313f3952ffad8f19474995072c1b71ea1e566544 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Thu, 28 Mar 2019 16:08:31 +0200 Subject: [PATCH 248/603] magento/magento2#19987: Static test fix. --- app/code/Magento/Widget/Model/Widget/Config.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/code/Magento/Widget/Model/Widget/Config.php b/app/code/Magento/Widget/Model/Widget/Config.php index 5832a08f0df06..b259d4e6224be 100644 --- a/app/code/Magento/Widget/Model/Widget/Config.php +++ b/app/code/Magento/Widget/Model/Widget/Config.php @@ -120,6 +120,7 @@ public function getWidgetPlaceholderImageUrls() /** * Return url to error image + * * @return string */ public function getErrorImageUrl() @@ -129,6 +130,7 @@ public function getErrorImageUrl() /** * Return url to wysiwyg plugin + * * @return string */ public function getWysiwygJsPluginSrc() @@ -189,6 +191,8 @@ public function decodeWidgetsFromQuery($queryParam) } /** + * Get available widgets. + * * @param \Magento\Framework\DataObject $config Editor element config * @return array */ From cbdfcc32f11b5676907f97069a30c52135b9c278 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza Date: Thu, 28 Mar 2019 16:00:29 +0100 Subject: [PATCH 249/603] Refactoring --- ...efrontCustomerResetPasswordActionGroup.xml | 28 +++++++++++++++++ ...StorefrontCustomerLoginMessagesSection.xml | 1 + ...refrontResetCustomerPasswordFailedTest.xml | 30 +++++++------------ 3 files changed, 40 insertions(+), 19 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerResetPasswordActionGroup.xml diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerResetPasswordActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerResetPasswordActionGroup.xml new file mode 100644 index 0000000000000..2c641317c6e9a --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerResetPasswordActionGroup.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerLoginMessagesSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerLoginMessagesSection.xml index 078021db062cc..a9859cf58751b 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerLoginMessagesSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerLoginMessagesSection.xml @@ -11,5 +11,6 @@
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml index 7050050097874..684d0c0730c3f 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml @@ -22,26 +22,18 @@ + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + From 51c984e65956dcce1ffc259c8fbac13a1c48f7f7 Mon Sep 17 00:00:00 2001 From: Deepty Thampy Date: Thu, 28 Mar 2019 10:42:08 -0500 Subject: [PATCH 250/603] GraphQL-513: Test coverage for graphql GET support - added integration test for queries with parameterized variables --- .../Controller/GraphQlControllerTest.php | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php index 32dfa63b7ab70..59b29e3b5d0ce 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php @@ -180,6 +180,61 @@ public function testMutationWithHttpGet() $this->assertEquals('Mutation requests allowed only for POST requests', $output['errors'][0]); } + /** Test request is dispatched and response generated when using GET request with parameterized query string + * + * @return void + */ + public function testDispatchGetWithParameterizedVariables() : void + { + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + + /** @var ProductInterface $product */ + $product = $productRepository->get('simple1'); + $query1 = <<<'QUERY' + + query GetProducts($filterInput:ProductFilterInput){ + products( + filter:$filterInput +){ + items{ + id + name + sku + } +} + +} +QUERY; + $variables = [ + 'filterInput'=>[ + 'sku' =>['eq' => 'simple1'] + ] + ]; + $postData = [ + 'query' => $query1, + 'variables' => json_encode($variables), + 'operationName' => null + ]; + + + /** @var Http $request */ + $request = $this->objectManager->get(Http::class); + $request->setPathInfo('/graphql'); + $request->setMethod('GET'); + $request->setParams($postData); + $response = $this->graphql->dispatch($request); + $output = $this->jsonSerializer->unserialize($response->getContent()); + $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); + + $this->assertArrayNotHasKey('errors', $output, 'Response has errors'); + $this->assertTrue(!empty($output['data']['products']['items']), 'Products array has items'); + $this->assertTrue(!empty($output['data']['products']['items'][0]), 'Products array has items'); + $this->assertEquals($output['data']['products']['items'][0]['id'], $product->getData($linkField)); + $this->assertEquals($output['data']['products']['items'][0]['sku'], $product->getSku()); + $this->assertEquals($output['data']['products']['items'][0]['name'], $product->getName()); + } + /** * Test the errors on graphql output * From ed348f79eef1f741bafc950bc93e480d55503635 Mon Sep 17 00:00:00 2001 From: Daniel Renaud Date: Thu, 28 Mar 2019 13:09:41 -0500 Subject: [PATCH 251/603] 229: [GraphQL caching] Add support for queries via HTTP GET --- .../Magento/GraphQl/Controller/GraphQlControllerTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php index 59b29e3b5d0ce..6e8d60a177c5d 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php @@ -217,7 +217,6 @@ public function testDispatchGetWithParameterizedVariables() : void 'operationName' => null ]; - /** @var Http $request */ $request = $this->objectManager->get(Http::class); $request->setPathInfo('/graphql'); From 5ec72e426a1771ffca7da16d0d00bf905f15f016 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha Date: Thu, 28 Mar 2019 21:06:38 +0200 Subject: [PATCH 252/603] MAGETWO-70996: [GitHub] Customer Address "default billing address" Attribute Not Used in Checkout #8777 --- .../BraintreeCreditCardOnCheckoutTest.xml | 1 + .../Mftf/Section/CheckoutPaymentSection.xml | 1 + ...StorefrontCheckoutPaymentMethodSection.xml | 1 + ...ddressShouldBeCheckedOnPaymentPageTest.xml | 63 +++++++++++++++++++ .../Test/StorefrontCustomerCheckoutTest.xml | 19 +++--- ...OrderWithNewAddressesThatWasEditedTest.xml | 3 +- .../web/js/model/checkout-data-resolver.js | 9 +-- .../Test/TestCase/OnePageCheckoutTest.xml | 7 +-- .../TestStep/FillBillingInformationStep.php | 35 +++++++++-- .../payment/method-renderer/cc-form.test.js | 12 ++++ .../payment/method-renderer/paypal.test.js | 12 ++++ .../paypal-express-abstract.test.js | 12 ++++ 12 files changed, 152 insertions(+), 23 deletions(-) create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/DefaultBillingAddressShouldBeCheckedOnPaymentPageTest.xml diff --git a/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml b/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml index f27477ce8a672..84a3bbf8262d2 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml @@ -87,6 +87,7 @@ + diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml index 0206c18b819c2..f4d14fdcd827f 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml @@ -54,5 +54,6 @@ +
diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutPaymentMethodSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutPaymentMethodSection.xml index 55c4385706ba9..9d9a96d2ea5e6 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutPaymentMethodSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutPaymentMethodSection.xml @@ -12,5 +12,6 @@ + diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/DefaultBillingAddressShouldBeCheckedOnPaymentPageTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/DefaultBillingAddressShouldBeCheckedOnPaymentPageTest.xml new file mode 100644 index 0000000000000..86c466ad06034 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/DefaultBillingAddressShouldBeCheckedOnPaymentPageTest.xml @@ -0,0 +1,63 @@ + + + + + + + + + + <description value="Default billing address should be preselected on payments page on checkout if it exist"/> + <severity value="CRITICAL"/> + <testCaseId value="MAGETWO-98892"/> + <useCaseId value="MAGETWO-70996"/> + <group value="checkout"/> + </annotations> + <before> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="SimpleProduct" stepKey="createProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + </before> + <after> + <!--Logout from customer account--> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + </after> + <!--Go to Storefront as Customer--> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> + <argument name="Customer" value="$$createCustomer$$" /> + </actionGroup> + <!-- Add simple product to cart and go to checkout--> + <actionGroup ref="AddSimpleProductToCart" stepKey="addProductToCart"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> + <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart"/> + <!-- Click "+ New Address" and Fill new address--> + <click selector="{{CheckoutShippingSection.newAddressButton}}" stepKey="addAddress"/> + <actionGroup ref="LoggedInCheckoutWithOneAddressFieldWithoutStateField" stepKey="changeAddress"> + <argument name="Address" value="UK_Not_Default_Address"/> + <argument name="classPrefix" value="._show"/> + </actionGroup> + <!--Click "Save Addresses" --> + <click selector="{{CheckoutShippingSection.saveAddress}}" stepKey="saveAddress"/> + <waitForPageLoad stepKey="waitForAddressSaved"/> + <dontSeeElement selector="{{StorefrontCheckoutAddressPopupSection.newAddressModalPopup}}" stepKey="dontSeeModalPopup"/> + <!--Select Shipping Rate "Flat Rate" and click "Next" button--> + <click selector="{{CheckoutShippingMethodsSection.checkShippingMethodByName('Flat Rate')}}" stepKey="selectFlatShippingMethod"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask2"/> + <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickNext"/> + <!--Verify that "My billing and shipping address are the same" is unchecked and billing address is preselected--> + <dontSeeCheckboxIsChecked selector="{{CheckoutPaymentSection.billingAddressNotSameCheckbox}}" stepKey="shippingAndBillingAddressIsSameUnchecked"/> + <see selector="{{CheckoutPaymentSection.billingAddress}}" userInput="{{US_Address_TX.street[0]}}" stepKey="assertBillingAddress"/> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml index e7c2ad3dd28a4..c298e949fd9ea 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml @@ -196,7 +196,7 @@ <!-- Checkout select Check/Money Order payment --> <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyPayment2"/> <waitForElement stepKey="waitForPlaceOrderButton2" selector="{{CheckoutPaymentSection.placeOrder}}" time="30" /> - <see stepKey="seeBillingAddressIsCorrect2" selector="{{CheckoutPaymentSection.billingAddress}}" userInput="{{UK_Not_Default_Address.street[0]}}" /> + <see stepKey="seeBillingAddressIsCorrect2" selector="{{CheckoutPaymentSection.billingAddress}}" userInput="{{US_Address_NY.street[0]}}" /> <click stepKey="clickPlaceOrderButton2" selector="{{CheckoutPaymentSection.placeOrder}}" /> <waitForPageLoad stepKey="waitForOrderSuccessPage2"/> <see stepKey="seeSuccessMessage2" selector="{{CheckoutSuccessMainSection.success}}" userInput="Your order number is:" /> @@ -216,6 +216,7 @@ <createData entity="ApiSimpleProduct" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> </createData> + <magentoCLI stepKey="setShowBillingAddressOnCheckout" command="config:set checkout/options/display_billing_address_on 1" /> <magentoCLI stepKey="allowSpecificValue" command="config:set payment/checkmo/allowspecific 1" /> <magentoCLI stepKey="specificCountryValue" command="config:set payment/checkmo/specificcountry GB" /> <createData entity="Simple_US_Customer" stepKey="simpleuscustomer"/> @@ -226,6 +227,7 @@ <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <magentoCLI stepKey="allowSpecificValue" command="config:set payment/checkmo/allowspecific 0" /> <magentoCLI stepKey="specificCountryValue" command="config:set payment/checkmo/specificcountry ''" /> + <magentoCLI stepKey="setShowBillingAddressOnCheckout" command="config:set checkout/options/display_billing_address_on 0" /> </after> <!-- Login as Customer --> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> @@ -253,16 +255,19 @@ <dontsee selector="{{CheckoutPaymentSection.paymentMethodByName('Check / Money order')}}" stepKey="paymentMethodDoesNotAvailable"/> <!-- Fill UK Address and verify that payment available and checkout successful --> - <click selector="{{CheckoutHeaderSection.shippingMethodStep}}" stepKey="goToShipping" /> - <click selector="{{CheckoutShippingSection.newAddressButton}}" stepKey="fillNewAddress" /> - <actionGroup ref="LoggedInUserCheckoutAddNewShippingSectionWithoutRegionActionGroup" stepKey="customerCheckoutFillingShippingSectionUK"> - <argument name="customerVar" value="CustomerEntityOne" /> - <argument name="customerAddressVar" value="UK_Not_Default_Address" /> + <click selector="{{StorefrontCheckoutPaymentMethodSection.billingAddressSameAsShippingShared}}" stepKey="UncheckCheckCheckBox"/> + <click selector="{{CheckoutShippingSection.addressDropdown}}" stepKey="clickOnAddressDropDown"/> + <click selector="{{CheckoutPaymentSection.addressOptionByName('New Address')}}" stepKey="clickOnNewAddress"/> + <waitForPageLoad stepKey="waitNewAddressBillingForm"/> + <actionGroup ref="LoggedInCheckoutFillNewBillingAddressActionGroup" stepKey="changeAddress"> + <argument name="Address" value="updateCustomerUKAddress"/> + <argument name="classPrefix" value="[aria-hidden=false]"/> </actionGroup> + <click selector="{{CheckoutPaymentSection.addressAction('Update')}}" stepKey="clickUpdateBillingAddressButton" /> <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="customerSelectCheckMoneyOrderPayment" /> <actionGroup ref="CheckoutPlaceOrderActionGroup" stepKey="customerPlaceorder"> <argument name="orderNumberMessage" value="CONST.successCheckoutOrderNumberMessage" /> <argument name="emailYouMessage" value="CONST.successCheckoutEmailYouMessage" /> </actionGroup> </test> -</tests> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerPlaceOrderWithNewAddressesThatWasEditedTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerPlaceOrderWithNewAddressesThatWasEditedTest.xml index 8537e10ce5a03..651c5bd8d4375 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerPlaceOrderWithNewAddressesThatWasEditedTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerPlaceOrderWithNewAddressesThatWasEditedTest.xml @@ -71,6 +71,7 @@ <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickNext"/> <!--Refresh Page and Place Order--> + <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyPayment"/> <reloadPage stepKey="reloadPage"/> <waitForElement selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="waitForPlaceOrderButton"/> <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrder"/> @@ -89,7 +90,7 @@ <amOnPage url="{{StorefrontCustomerOrderViewPage.url({$grabOrderNumber})}}" stepKey="goToOrderReviewPage"/> <see userInput="{{UK_Not_Default_Address.street[0]}} {{UK_Not_Default_Address.city}}, {{UK_Not_Default_Address.postcode}}" selector="{{StorefrontCustomerOrderViewSection.shippingAddress}}" stepKey="checkShippingAddress"/> - <see userInput="{{UK_Not_Default_Address.street[0]}} {{UK_Not_Default_Address.city}}, {{UK_Not_Default_Address.postcode}}" + <see userInput="{{US_Address_TX_Default_Billing.street[0]}}" selector="{{StorefrontCustomerOrderViewSection.billingAddress}}" stepKey="checkBillingAddress"/> </test> </tests> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js b/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js index 9cc60a3645d58..8f468e9966906 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js @@ -243,15 +243,12 @@ define([ return; } - if (quote.isVirtual()) { - isBillingAddressInitialized = addressList.some(function (addrs) { + if (quote.isVirtual() || !quote.billingAddress()) { + addressList.some(function (addrs) { if (addrs.isDefaultBilling()) { selectBillingAddress(addrs); - - return true; + isBillingAddressInitialized = true; } - - return false; }); } diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.xml index 0edd8f4183f30..daf9aaae50580 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.xml @@ -15,13 +15,11 @@ <data name="shippingAddressCustomer" xsi:type="array"> <item name="added" xsi:type="number">1</item> </data> - <data name="billingAddressCustomer" xsi:type="array"> - <item name="added" xsi:type="number">1</item> - </data> <data name="prices" xsi:type="array"> <item name="grandTotal" xsi:type="string">565.00</item> </data> <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="editBillingInformation" xsi:type="boolean">false</data> <data name="shipping/shipping_method" xsi:type="string">Fixed</data> <data name="payment/method" xsi:type="string">checkmo</data> <data name="configData" xsi:type="string">checkmo</data> @@ -43,6 +41,7 @@ <item name="grandTotal" xsi:type="string">565.00</item> </data> <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="editBillingInformation" xsi:type="boolean">false</data> <data name="shipping/shipping_method" xsi:type="string">Fixed</data> <data name="payment/method" xsi:type="string">checkmo</data> <data name="configData" xsi:type="string">checkmo</data> @@ -61,7 +60,7 @@ <data name="shippingAddress/dataset" xsi:type="string">UK_address_without_email</data> <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> <data name="shipping/shipping_method" xsi:type="string">Fixed</data> - <data name="billingCheckboxState" xsi:type="string">Yes</data> + <data name="editBillingInformation" xsi:type="boolean">false</data> <data name="billingAddress/dataset" xsi:type="string">US_address_1_without_email</data> <data name="payment/method" xsi:type="string">checkmo</data> <data name="configData" xsi:type="string">checkmo</data> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php index aa7eba634145f..cf2f99a78cefb 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php @@ -126,11 +126,15 @@ public function run() if ($this->billingCheckboxState) { $this->assertBillingAddressCheckbox->processAssert($this->checkoutOnepage, $this->billingCheckboxState); } - if ($this->billingCheckboxState === 'Yes' && !$this->editBillingInformation) { - return [ - 'billingAddress' => $this->shippingAddress - ]; + + if (!$this->editBillingInformation) { + $billingAddress = $this->billingCheckboxState === 'Yes' + ? $this->shippingAddress + : $this->getDefaultBillingAddress(); + + return ['billingAddress' => $billingAddress]; } + if ($this->billingAddress) { $selectedPaymentMethod = $this->checkoutOnepage->getPaymentBlock()->getSelectedPaymentMethodBlock(); if ($this->shippingAddress) { @@ -139,9 +143,11 @@ public function run() $selectedPaymentMethod->getBillingBlock()->fillBilling($this->billingAddress); $billingAddress = $this->billingAddress; } + if (isset($this->billingAddressCustomer['added'])) { $addressIndex = $this->billingAddressCustomer['added']; - $billingAddress = $this->customer->getDataFieldConfig('address')['source']->getAddresses()[$addressIndex]; + $billingAddress = $this->customer->getDataFieldConfig('address')['source'] + ->getAddresses()[$addressIndex]; $address = $this->objectManager->create( \Magento\Customer\Test\Block\Address\Renderer::class, ['address' => $billingAddress, 'type' => 'html_for_select_element'] @@ -156,4 +162,23 @@ public function run() 'billingAddress' => $billingAddress ]; } + + /** + * Get default billing address + * + * @return Address|null + */ + private function getDefaultBillingAddress() + { + $addresses = $this->customer->getDataFieldConfig('address')['source']->getAddresses(); + $defaultAddress = null; + foreach ($addresses as $address) { + if ($address->getDefaultBilling() === 'Yes') { + $defaultAddress = $address; + break; + } + } + + return $defaultAddress; + } } diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Braintree/frontend/js/view/payment/method-renderer/cc-form.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Braintree/frontend/js/view/payment/method-renderer/cc-form.test.js index 8fdef2cbaadbb..429342b43bcb2 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Braintree/frontend/js/view/payment/method-renderer/cc-form.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Braintree/frontend/js/view/payment/method-renderer/cc-form.test.js @@ -15,6 +15,18 @@ define([ describe('Magento_Braintree/js/view/payment/method-renderer/cc-form', function () { var injector = new Squire(), mocks = { + 'Magento_Checkout/js/model/checkout-data-resolver': { + + /** Stub */ + applyBillingAddress: function () { + return true; + }, + + /** Stub */ + resolveBillingAddress: function () { + return true; + } + }, 'Magento_Checkout/js/model/quote': { billingAddress: ko.observable(), shippingAddress: ko.observable(), diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Braintree/frontend/js/view/payment/method-renderer/paypal.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Braintree/frontend/js/view/payment/method-renderer/paypal.test.js index 4fc73caf7e14b..6ba0ed0b58f03 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Braintree/frontend/js/view/payment/method-renderer/paypal.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Braintree/frontend/js/view/payment/method-renderer/paypal.test.js @@ -14,6 +14,18 @@ define([ var injector = new Squire(), mocks = { + 'Magento_Checkout/js/model/checkout-data-resolver': { + + /** Stub */ + applyBillingAddress: function () { + return true; + }, + + /** Stub */ + resolveBillingAddress: function () { + return true; + } + }, 'Magento_Checkout/js/model/quote': { billingAddress: ko.observable(), shippingAddress: ko.observable({ diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Paypal/frontend/js/view/payment/method-renderer/paypal-express-abstract.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Paypal/frontend/js/view/payment/method-renderer/paypal-express-abstract.test.js index 29a2e8db914a7..7bc9a2a0113aa 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Paypal/frontend/js/view/payment/method-renderer/paypal-express-abstract.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Paypal/frontend/js/view/payment/method-renderer/paypal-express-abstract.test.js @@ -24,6 +24,18 @@ define([ return true; }).and.callThrough(), mocks = { + 'Magento_Checkout/js/model/checkout-data-resolver': { + + /** Stub */ + applyBillingAddress: function () { + return true; + }, + + /** Stub */ + resolveBillingAddress: function () { + return true; + } + }, 'Magento_Checkout/js/model/quote': { billingAddress: ko.observable(), shippingAddress: ko.observable(), From fb4c3b622a86aec63133b716aa6319c3d6a79a6a Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Fri, 29 Mar 2019 10:11:59 +0300 Subject: [PATCH 253/603] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Gateway URL changed to https; --- app/code/Magento/Ups/Model/Carrier.php | 2 +- app/code/Magento/Ups/etc/config.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index 8c60f5a53a2d9..75ce0c3014efa 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -77,7 +77,7 @@ class Carrier extends AbstractCarrierOnline implements CarrierInterface * * @var string */ - protected $_defaultCgiGatewayUrl = 'http://www.ups.com:80/using/services/rave/qcostcgi.cgi'; + protected $_defaultCgiGatewayUrl = 'https://www.ups.com:80/using/services/rave/qcostcgi.cgi'; /** * Test urls for shipment diff --git a/app/code/Magento/Ups/etc/config.xml b/app/code/Magento/Ups/etc/config.xml index e2ac1c6d6c443..791b325c65e3f 100644 --- a/app/code/Magento/Ups/etc/config.xml +++ b/app/code/Magento/Ups/etc/config.xml @@ -19,7 +19,7 @@ <cutoff_cost /> <dest_type>RES</dest_type> <free_method>GND</free_method> - <gateway_url>http://www.ups.com/using/services/rave/qcostcgi.cgi</gateway_url> + <gateway_url>https://www.ups.com/using/services/rave/qcostcgi.cgi</gateway_url> <gateway_xml_url>https://onlinetools.ups.com/ups.app/xml/Rate</gateway_xml_url> <handling>0</handling> <model>Magento\Ups\Model\Carrier</model> From 7fa9e19004a3cdb9a07224d6da37a0519b722224 Mon Sep 17 00:00:00 2001 From: Ventimiglia Samuel <sam.ventimiglia@gmail.com> Date: Fri, 29 Mar 2019 09:29:44 +0100 Subject: [PATCH 254/603] Removed two times zlib.output_compression on ## Enable resulting html compression #php_flag zlib.output_compression on ########################################### --- pub/.htaccess | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pub/.htaccess b/pub/.htaccess index 926c012eef6a5..64166f1727c84 100644 --- a/pub/.htaccess +++ b/pub/.htaccess @@ -47,11 +47,6 @@ php_flag session.auto_start off ############################################ -## Enable resulting html compression - - #php_flag zlib.output_compression on - -########################################### # Disable user agent verification to not break multiple image upload php_flag suhosin.session.cryptua off From 423f92c698de842123b250f0caa578bdc791a47a Mon Sep 17 00:00:00 2001 From: Yuliya Labudova <Yuliya_Labudova@epam.com> Date: Fri, 29 Mar 2019 14:35:43 +0300 Subject: [PATCH 255/603] MAGETWO-96429: Wrong special price displayed in product search results - Delete preference for price; - Deprecate class. --- .../Magento/Catalog/Model/Product/Type/FrontSpecialPrice.php | 5 +++++ app/code/Magento/Catalog/etc/frontend/di.xml | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Product/Type/FrontSpecialPrice.php b/app/code/Magento/Catalog/Model/Product/Type/FrontSpecialPrice.php index f6893a41113e6..dabfdb74f0118 100644 --- a/app/code/Magento/Catalog/Model/Product/Type/FrontSpecialPrice.php +++ b/app/code/Magento/Catalog/Model/Product/Type/FrontSpecialPrice.php @@ -17,6 +17,9 @@ * * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * + * @deprecated + * @see \Magento\Catalog\Model\Product\Type\Price */ class FrontSpecialPrice extends Price { @@ -66,6 +69,8 @@ public function __construct( /** * @inheritdoc + * + * @deprecated */ protected function _applySpecialPrice($product, $finalPrice) { diff --git a/app/code/Magento/Catalog/etc/frontend/di.xml b/app/code/Magento/Catalog/etc/frontend/di.xml index 793a2291f599c..ee9c5b29da894 100644 --- a/app/code/Magento/Catalog/etc/frontend/di.xml +++ b/app/code/Magento/Catalog/etc/frontend/di.xml @@ -120,5 +120,4 @@ <plugin name="catalog_app_action_dispatch_controller_context_plugin" type="Magento\Catalog\Plugin\Framework\App\Action\ContextPlugin" /> </type> - <preference for="Magento\Catalog\Model\Product\Type\Price" type="Magento\Catalog\Model\Product\Type\FrontSpecialPrice" /> </config> From bbe71ef43062429cd3f235ad885cc3a996e7628d Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Fri, 29 Mar 2019 13:44:55 +0200 Subject: [PATCH 256/603] refactoring --- .../Magento/CatalogSearch/Model/Layer/Filter/Decimal.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php b/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php index a5e9f9ef0a331..e9fb1070fedd5 100644 --- a/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php +++ b/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php @@ -111,12 +111,9 @@ protected function _getItemsData() $from = ''; } if ($to == '*') { - $to = ''; + $to = null; } - $label = $this->renderRangeLabel( - empty($from) ? 0 : $from, - empty($to) ? $to : $to - ); + $label = $this->renderRangeLabel(empty($from) ? 0 : $from, $to); $value = $from . '-' . $to; $data[] = [ @@ -141,7 +138,7 @@ protected function _getItemsData() protected function renderRangeLabel($fromPrice, $toPrice) { $formattedFromPrice = $this->priceCurrency->format($fromPrice); - if ($toPrice === '') { + if ($toPrice === null) { return __('%1 and above', $formattedFromPrice); } else { if ($fromPrice != $toPrice) { From 2de902a700424e0c41d7386e806a4d2e23282ccb Mon Sep 17 00:00:00 2001 From: Vishal Sutariya <vishalsutariya7037@gmail.com> Date: Fri, 29 Mar 2019 17:35:32 +0530 Subject: [PATCH 257/603] Fixed typo error in sales grid at admin --- .../view/adminhtml/ui_component/sales_order_creditmemo_grid.xml | 2 +- .../view/adminhtml/ui_component/sales_order_shipment_grid.xml | 2 +- .../adminhtml/ui_component/sales_order_view_creditmemo_grid.xml | 2 +- .../adminhtml/ui_component/sales_order_view_shipment_grid.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) 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 f36a7d2821f7a..e0b7dae8fdb1a 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 @@ -92,7 +92,7 @@ <column name="order_increment_id"> <settings> <filter>text</filter> - <label translate="true">Order</label> + <label translate="true">Order #</label> </settings> </column> <column name="order_created_at" class="Magento\Ui\Component\Listing\Columns\Date" component="Magento_Ui/js/grid/columns/date"> diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml index e0495e62d5ce1..9e02c31a20635 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml @@ -100,7 +100,7 @@ <column name="order_increment_id"> <settings> <filter>text</filter> - <label translate="true">Order</label> + <label translate="true">Order #</label> </settings> </column> <column name="order_created_at" class="Magento\Ui\Component\Listing\Columns\Date" component="Magento_Ui/js/grid/columns/date"> 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 10b7b1c028c66..cf536c27a0ac3 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 @@ -105,7 +105,7 @@ <column name="order_increment_id"> <settings> <filter>text</filter> - <label translate="true">Order</label> + <label translate="true">Order #</label> </settings> </column> <column name="order_created_at" class="Magento\Ui\Component\Listing\Columns\Date" component="Magento_Ui/js/grid/columns/date"> diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml index 6db77a79b8c14..5f8ebde290664 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml @@ -106,7 +106,7 @@ <column name="order_increment_id"> <settings> <filter>textRange</filter> - <label translate="true">Order</label> + <label translate="true">Order #</label> </settings> </column> <column name="order_created_at" class="Magento\Ui\Component\Listing\Columns\Date" component="Magento_Ui/js/grid/columns/date"> From 0b7455fa35795a6835bebb15ec25009689f0605e Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Fri, 29 Mar 2019 14:24:23 +0200 Subject: [PATCH 258/603] MAGETWO-70996: [GitHub] Customer Address "default billing address" Attribute Not Used in Checkout #8777 --- .../BraintreeCreditCardOnCheckoutTest.xml | 4 -- .../Mftf/Section/CheckoutPaymentSection.xml | 2 +- ...ddressShouldBeCheckedOnPaymentPageTest.xml | 14 +++---- .../Test/StorefrontCustomerCheckoutTest.xml | 38 +++++++++---------- .../web/js/model/checkout-data-resolver.js | 7 +++- 5 files changed, 32 insertions(+), 33 deletions(-) diff --git a/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml b/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml index 84a3bbf8262d2..d701993be2c4c 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml @@ -87,10 +87,6 @@ <waitForPageLoad stepKey="waitForPageLoad10"/> <click selector="{{BraintreeConfigurationPaymentSection.paymentMethod}}" stepKey="SelectBraintreePaymentMethod1"/> <waitForPageLoad stepKey="waitForPageLoad11"/> - <click selector="{{CheckoutPaymentSection.shippingAndBillingAddressSame}}" stepKey="CheckCheckBox"/> - <click selector="{{CheckoutPaymentSection.shippingAndBillingAddressSame}}" stepKey="UncheckCheckBox"/> - - <click selector="{{CheckoutShippingSection.updateAddress}}" stepKey="clickToUpdate"/> <waitForPageLoad stepKey="waitForPageLoad12"/> <!--Place order--> <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="PlaceOrder1"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml index f4d14fdcd827f..7acfc14111b6f 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml @@ -54,6 +54,6 @@ <element name="addressBook" type="button" selector="//a[text()='Address Book']"/> <element name="noQuotes" type="text" selector=".no-quotes-block"/> <element name="paymentMethodByName" type="text" selector="//*[@id='checkout-payment-method-load']//*[contains(@class, 'payment-group')]//label[normalize-space(.)='{{var1}}']" parameterized="true"/> - <element name="addressOptionByName" type="text" selector=" //option[text()='{{action}}']" parameterized="true"/> + <element name="billingAddressSelect" type="select" selector="select[name='billing_address_id']"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/DefaultBillingAddressShouldBeCheckedOnPaymentPageTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/DefaultBillingAddressShouldBeCheckedOnPaymentPageTest.xml index 86c466ad06034..166f5022d5aeb 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/DefaultBillingAddressShouldBeCheckedOnPaymentPageTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/DefaultBillingAddressShouldBeCheckedOnPaymentPageTest.xml @@ -25,18 +25,18 @@ <requiredEntity createDataKey="createCategory"/> </createData> <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + <!--Go to Storefront as Customer--> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> + <argument name="Customer" value="$$createCustomer$$" /> + </actionGroup> </before> <after> - <!--Logout from customer account--> - <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <!--Logout from customer account--> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> </after> - <!--Go to Storefront as Customer--> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> - <argument name="Customer" value="$$createCustomer$$" /> - </actionGroup> <!-- Add simple product to cart and go to checkout--> <actionGroup ref="AddSimpleProductToCart" stepKey="addProductToCart"> <argument name="product" value="$$createProduct$$"/> @@ -53,7 +53,7 @@ <waitForPageLoad stepKey="waitForAddressSaved"/> <dontSeeElement selector="{{StorefrontCheckoutAddressPopupSection.newAddressModalPopup}}" stepKey="dontSeeModalPopup"/> <!--Select Shipping Rate "Flat Rate" and click "Next" button--> - <click selector="{{CheckoutShippingMethodsSection.checkShippingMethodByName('Flat Rate')}}" stepKey="selectFlatShippingMethod"/> + <actionGroup ref="CheckoutSelectFlatRateShippingMethodActionGroup" stepKey="selectFlatRateShipping"/> <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask2"/> <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickNext"/> <!--Verify that "My billing and shipping address are the same" is unchecked and billing address is preselected--> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml index c298e949fd9ea..13b7be6e3c411 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml @@ -186,20 +186,20 @@ <see selector="{{StorefrontMinicartSection.quantity}}" userInput="1" stepKey="seeCartQuantity2"/> <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart2" /> - <click stepKey="changeShippingAddress" selector="{{CheckoutShippingMethodsSection.shipHereButton}}"/> - <waitForElementNotVisible stepKey="waitForShippingMethodLoaderNotVisible" selector="{{CheckoutShippingMethodsSection.shippingMethodLoader}}" time="30"/> - <waitForElementVisible stepKey="waitForShippingMethodRadioToBeVisible" selector="{{CheckoutShippingMethodsSection.firstShippingMethod}}" time="30"/> + <click selector="{{CheckoutShippingMethodsSection.shipHereButton}}" stepKey="changeShippingAddress"/> + <waitForElementNotVisible selector="{{CheckoutShippingMethodsSection.shippingMethodLoader}}" time="30" stepKey="waitForShippingMethodLoaderNotVisible"/> + <waitForElementVisible selector="{{CheckoutShippingMethodsSection.firstShippingMethod}}" time="30" stepKey="waitForShippingMethodRadioToBeVisible"/> <waitForPageLoad stepKey="waitForPageLoad23"/> - <click stepKey="selectFirstShippingMethod2" selector="{{CheckoutShippingMethodsSection.firstShippingMethod}}"/> - <waitForElement stepKey="waitForShippingMethodSelect2" selector="{{CheckoutShippingMethodsSection.next}}" time="30"/> - <click stepKey="clickNextOnShippingMethodLoad2" selector="{{CheckoutShippingMethodsSection.next}}" /> + <click selector="{{CheckoutShippingMethodsSection.firstShippingMethod}}" stepKey="selectFirstShippingMethod2"/> + <waitForElement selector="{{CheckoutShippingMethodsSection.next}}" time="30" stepKey="waitForShippingMethodSelect2"/> + <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickNextOnShippingMethodLoad2"/> <!-- Checkout select Check/Money Order payment --> <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyPayment2"/> - <waitForElement stepKey="waitForPlaceOrderButton2" selector="{{CheckoutPaymentSection.placeOrder}}" time="30" /> - <see stepKey="seeBillingAddressIsCorrect2" selector="{{CheckoutPaymentSection.billingAddress}}" userInput="{{US_Address_NY.street[0]}}" /> - <click stepKey="clickPlaceOrderButton2" selector="{{CheckoutPaymentSection.placeOrder}}" /> + <waitForElement selector="{{CheckoutPaymentSection.placeOrder}}" time="30" stepKey="waitForPlaceOrderButton2"/> + <see selector="{{CheckoutPaymentSection.billingAddress}}" userInput="{{US_Address_NY.street[0]}}" stepKey="seeBillingAddressIsCorrect2" /> + <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrderButton2"/> <waitForPageLoad stepKey="waitForOrderSuccessPage2"/> - <see stepKey="seeSuccessMessage2" selector="{{CheckoutSuccessMainSection.success}}" userInput="Your order number is:" /> + <see selector="{{CheckoutSuccessMainSection.success}}" userInput="Your order number is:" stepKey="seeSuccessMessage2"/> </test> <test name="StorefrontCustomerCheckoutTestWithRestrictedCountriesForPayment"> <annotations> @@ -216,18 +216,18 @@ <createData entity="ApiSimpleProduct" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <magentoCLI stepKey="setShowBillingAddressOnCheckout" command="config:set checkout/options/display_billing_address_on 1" /> - <magentoCLI stepKey="allowSpecificValue" command="config:set payment/checkmo/allowspecific 1" /> - <magentoCLI stepKey="specificCountryValue" command="config:set payment/checkmo/specificcountry GB" /> + <magentoCLI command="config:set checkout/options/display_billing_address_on 1" stepKey="setShowBillingAddressOnPaymentPage" /> + <magentoCLI command="config:set payment/checkmo/allowspecific 1" stepKey="allowSpecificValue" /> + <magentoCLI command="config:set payment/checkmo/specificcountry GB" stepKey="specificCountryValue" /> <createData entity="Simple_US_Customer" stepKey="simpleuscustomer"/> </before> <after> - <amOnPage url="{{AdminLogoutPage.url}}" stepKey="amOnLogoutPage"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <magentoCLI stepKey="allowSpecificValue" command="config:set payment/checkmo/allowspecific 0" /> - <magentoCLI stepKey="specificCountryValue" command="config:set payment/checkmo/specificcountry ''" /> - <magentoCLI stepKey="setShowBillingAddressOnCheckout" command="config:set checkout/options/display_billing_address_on 0" /> + <magentoCLI command="config:set payment/checkmo/allowspecific 0" stepKey="allowSpecificValue" /> + <magentoCLI command="config:set payment/checkmo/specificcountry ''" stepKey="specificCountryValue" /> + <magentoCLI command="config:set checkout/options/display_billing_address_on 0" stepKey="setDisplayBillingAddressOnPaymentMethod" /> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> </after> <!-- Login as Customer --> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> @@ -255,9 +255,9 @@ <dontsee selector="{{CheckoutPaymentSection.paymentMethodByName('Check / Money order')}}" stepKey="paymentMethodDoesNotAvailable"/> <!-- Fill UK Address and verify that payment available and checkout successful --> - <click selector="{{StorefrontCheckoutPaymentMethodSection.billingAddressSameAsShippingShared}}" stepKey="UncheckCheckCheckBox"/> + <uncheckOption selector="{{StorefrontCheckoutPaymentMethodSection.billingAddressSameAsShippingShared}}" stepKey="uncheckBillingAddressSameAsShippingCheckCheckBox"/> <click selector="{{CheckoutShippingSection.addressDropdown}}" stepKey="clickOnAddressDropDown"/> - <click selector="{{CheckoutPaymentSection.addressOptionByName('New Address')}}" stepKey="clickOnNewAddress"/> + <selectOption selector="{{CheckoutPaymentSection.billingAddressSelect}}" userInput="New Address" stepKey="clickOnNewAddress"/> <waitForPageLoad stepKey="waitNewAddressBillingForm"/> <actionGroup ref="LoggedInCheckoutFillNewBillingAddressActionGroup" stepKey="changeAddress"> <argument name="Address" value="updateCustomerUKAddress"/> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js b/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js index 8f468e9966906..e54f464f24d02 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js @@ -244,11 +244,14 @@ define([ } if (quote.isVirtual() || !quote.billingAddress()) { - addressList.some(function (addrs) { + isBillingAddressInitialized = addressList.some(function (addrs) { if (addrs.isDefaultBilling()) { selectBillingAddress(addrs); - isBillingAddressInitialized = true; + + return true; } + + return false; }); } From c7e1defe63e859c2a1e19bcf736234533b3fa21b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Me=CC=81ndez=20Calzada?= <gonzalo.mendez@interactiv4.com> Date: Fri, 29 Mar 2019 14:18:26 +0100 Subject: [PATCH 259/603] Add multibyte support for attributeSource getOptionId method --- .../Attribute/Source/AbstractSource.php | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php index 36ad026029056..0e547e0887c30 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php @@ -88,7 +88,7 @@ public function getOptionText($value) public function getOptionId($value) { foreach ($this->getAllOptions() as $option) { - if (strcasecmp($option['label'], $value) == 0 || $option['value'] == $value) { + if ($this->mbStrcasecmp($option['label'], $value) == 0 || $option['value'] == $value) { return $option['value']; } } @@ -166,4 +166,22 @@ public function toOptionArray() { return $this->getAllOptions(); } + + /** + * Multibyte support strcasecmp function version + * @param string $str1 + * @param string $str2 + * @param null|string $encoding + * @return int|\\lt + */ + private function mbStrcasecmp($str1, $str2, $encoding = null) + { + if (null === $encoding) { + $encoding = mb_internal_encoding(); + } + return strcmp( + mb_strtoupper($str1, $encoding), + mb_strtoupper($str2, $encoding) + ); + } } From 7c6d41a07595e6fee7d416fe4921739d1e32e19e Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Fri, 29 Mar 2019 15:22:56 +0200 Subject: [PATCH 260/603] MAGETWO-97423: Price column in sales_order_item table shows the price including tax when Custom Price is applied on admin order --- .../Sales/Total/Quote/CommonTaxCollector.php | 3 + .../Total/Quote/CommonTaxCollectorTest.php | 130 +++++++++++++----- .../Tax/Model/Sales/Total/Quote/SetupUtil.php | 17 ++- .../including_tax_with_custom_price.php | 93 +++++++++++++ .../tax_calculation_data_aggregated.php | 2 + 5 files changed, 213 insertions(+), 32 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_with_custom_price.php diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php index bff489ee50c2f..31d5deb7ea0d5 100644 --- a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php +++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php @@ -688,6 +688,9 @@ public function updateItemTaxInfo($quoteItem, $itemTaxDetails, $baseItemTaxDetai { //The price should be base price $quoteItem->setPrice($baseItemTaxDetails->getPrice()); + if ($quoteItem->getCustomPrice() && $this->taxHelper->applyTaxOnCustomPrice()) { + $quoteItem->setCustomPrice($baseItemTaxDetails->getPrice()); + } $quoteItem->setConvertedPrice($itemTaxDetails->getPrice()); $quoteItem->setPriceInclTax($itemTaxDetails->getPriceInclTax()); $quoteItem->setRowTotal($itemTaxDetails->getRowTotal()); diff --git a/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/CommonTaxCollectorTest.php b/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/CommonTaxCollectorTest.php index 9325ec10dc627..711ead4625659 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/CommonTaxCollectorTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/CommonTaxCollectorTest.php @@ -3,79 +3,106 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Tax\Test\Unit\Model\Sales\Total\Quote; -/** - * Test class for \Magento\Tax\Model\Sales\Total\Quote\Tax - */ use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Tax\Helper\Data as TaxHelper; +use Magento\Tax\Api\Data\TaxDetailsItemInterface; +use Magento\Quote\Model\Quote\Item as QuoteItem; +use Magento\Store\Model\Store; +use Magento\Tax\Model\Sales\Total\Quote\CommonTaxCollector; +use Magento\Tax\Model\Config; +use Magento\Quote\Model\Quote\Address as QuoteAddress; +use Magento\Quote\Model\Quote; +use Magento\Tax\Api\Data\QuoteDetailsItemInterface; +use Magento\Tax\Api\Data\TaxClassKeyInterface; +use Magento\Tax\Model\Sales\Quote\ItemDetails; +use Magento\Tax\Model\TaxClass\Key as TaxClassKey; +use Magento\Tax\Api\Data\QuoteDetailsItemInterfaceFactory; +use Magento\Tax\Api\Data\TaxClassKeyInterfaceFactory; +use Magento\Quote\Api\Data\ShippingAssignmentInterface; +use Magento\Quote\Api\Data\ShippingInterface; +use Magento\Quote\Model\Quote\Address\Total as QuoteAddressTotal; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; /** + * Common tax collector test + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class CommonTaxCollectorTest extends \PHPUnit\Framework\TestCase +class CommonTaxCollectorTest extends TestCase { /** - * @var \Magento\Tax\Model\Sales\Total\Quote\CommonTaxCollector + * @var CommonTaxCollector */ private $commonTaxCollector; /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Tax\Model\Config + * @var MockObject|Config */ private $taxConfig; /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Quote\Model\Quote\Address + * @var MockObject|QuoteAddress */ private $address; /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Quote\Model\Quote + * @var MockObject|Quote */ private $quote; /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Store\Model\Store + * @var MockObject|Store */ private $store; /** - * @var \PHPUnit_Framework_MockObject_MockObject| + * @var MockObject */ protected $taxClassKeyDataObjectFactoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject| + * @var MockObject */ protected $quoteDetailsItemDataObjectFactoryMock; /** - * @var \Magento\Tax\Api\Data\QuoteDetailsItemInterface + * @var QuoteDetailsItemInterface */ protected $quoteDetailsItemDataObject; /** - * @var \Magento\Tax\Api\Data\TaxClassKeyInterface + * @var TaxClassKeyInterface */ protected $taxClassKeyDataObject; + /** + * @var TaxHelper + */ + protected $taxHelper; + + /** + * {@inheritdoc} + */ protected function setUp() { $objectManager = new ObjectManager($this); - $this->taxConfig = $this->getMockBuilder(\Magento\Tax\Model\Config::class) + $this->taxConfig = $this->getMockBuilder(Config::class) ->disableOriginalConstructor() - ->setMethods(['getShippingTaxClass', 'shippingPriceIncludesTax']) + ->setMethods(['getShippingTaxClass', 'shippingPriceIncludesTax', 'discountTax']) ->getMock(); - $this->store = $this->getMockBuilder(\Magento\Store\Model\Store::class) + $this->store = $this->getMockBuilder(Store::class) ->disableOriginalConstructor() ->setMethods(['__wakeup']) ->getMock(); - $this->quote = $this->getMockBuilder(\Magento\Quote\Model\Quote::class) + $this->quote = $this->getMockBuilder(Quote::class) ->disableOriginalConstructor() ->setMethods(['__wakeup', 'getStore']) ->getMock(); @@ -84,7 +111,7 @@ protected function setUp() ->method('getStore') ->will($this->returnValue($this->store)); - $this->address = $this->getMockBuilder(\Magento\Quote\Model\Quote\Address::class) + $this->address = $this->getMockBuilder(QuoteAddress::class) ->disableOriginalConstructor() ->getMock(); @@ -92,31 +119,35 @@ protected function setUp() ->method('getQuote') ->will($this->returnValue($this->quote)); $methods = ['create']; - $this->quoteDetailsItemDataObject = $objectManager->getObject( - \Magento\Tax\Model\Sales\Quote\ItemDetails::class - ); - $this->taxClassKeyDataObject = $objectManager->getObject(\Magento\Tax\Model\TaxClass\Key::class); + $this->quoteDetailsItemDataObject = $objectManager->getObject(ItemDetails::class); + $this->taxClassKeyDataObject = $objectManager->getObject(TaxClassKey::class); $this->quoteDetailsItemDataObjectFactoryMock - = $this->createPartialMock(\Magento\Tax\Api\Data\QuoteDetailsItemInterfaceFactory::class, $methods); + = $this->createPartialMock(QuoteDetailsItemInterfaceFactory::class, $methods); $this->quoteDetailsItemDataObjectFactoryMock->expects($this->any()) ->method('create') ->willReturn($this->quoteDetailsItemDataObject); $this->taxClassKeyDataObjectFactoryMock = - $this->createPartialMock(\Magento\Tax\Api\Data\TaxClassKeyInterfaceFactory::class, $methods); + $this->createPartialMock(TaxClassKeyInterfaceFactory::class, $methods); $this->taxClassKeyDataObjectFactoryMock->expects($this->any()) ->method('create') ->willReturn($this->taxClassKeyDataObject); + $this->taxHelper = $this->getMockBuilder(TaxHelper::class) + ->disableOriginalConstructor() + ->getMock(); $this->commonTaxCollector = $objectManager->getObject( - \Magento\Tax\Model\Sales\Total\Quote\CommonTaxCollector::class, + CommonTaxCollector::class, [ 'taxConfig' => $this->taxConfig, 'quoteDetailsItemDataObjectFactory' => $this->quoteDetailsItemDataObjectFactoryMock, - 'taxClassKeyDataObjectFactory' => $this->taxClassKeyDataObjectFactoryMock + 'taxClassKeyDataObjectFactory' => $this->taxClassKeyDataObjectFactoryMock, + 'taxHelper' => $this->taxHelper, ] ); } /** + * Test for GetShippingDataObject + * * @param array $addressData * @param bool $useBaseCurrency * @param string $shippingTaxClass @@ -128,8 +159,8 @@ public function testGetShippingDataObject( $useBaseCurrency, $shippingTaxClass, $shippingPriceInclTax - ) { - $shippingAssignmentMock = $this->createMock(\Magento\Quote\Api\Data\ShippingAssignmentInterface::class); + ): void { + $shippingAssignmentMock = $this->createMock(ShippingAssignmentInterface::class); $methods = [ 'getShippingDiscountAmount', 'getShippingTaxCalculationAmount', @@ -139,8 +170,10 @@ public function testGetShippingDataObject( 'getBaseShippingAmount', 'getBaseShippingDiscountAmount' ]; - $totalsMock = $this->createPartialMock(\Magento\Quote\Model\Quote\Address\Total::class, $methods); - $shippingMock = $this->createMock(\Magento\Quote\Api\Data\ShippingInterface::class); + /** @var MockObject|QuoteAddressTotal $totalsMock */ + $totalsMock = $this->createPartialMock(QuoteAddressTotal::class, $methods); + $shippingMock = $this->createMock(ShippingInterface::class); + /** @var MockObject|ShippingAssignmentInterface $shippingAssignmentMock */ $shippingAssignmentMock->expects($this->once())->method('getShipping')->willReturn($shippingMock); $shippingMock->expects($this->once())->method('getAddress')->willReturn($this->address); $baseShippingAmount = $addressData['base_shipping_amount']; @@ -184,9 +217,44 @@ public function testGetShippingDataObject( } /** + * Update item tax info + * + * @return void + */ + public function testUpdateItemTaxInfo(): void + { + /** @var MockObject|QuoteItem $quoteItem */ + $quoteItem = $this->getMockBuilder(QuoteItem::class) + ->disableOriginalConstructor() + ->setMethods(['getPrice', 'setPrice', 'getCustomPrice', 'setCustomPrice']) + ->getMock(); + $this->taxHelper->method('applyTaxOnCustomPrice')->willReturn(true); + $quoteItem->method('getCustomPrice')->willReturn(true); + /** @var MockObject|TaxDetailsItemInterface $itemTaxDetails */ + $itemTaxDetails = $this->getMockBuilder(TaxDetailsItemInterface::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var MockObject|TaxDetailsItemInterface $baseItemTaxDetails */ + $baseItemTaxDetails = $this->getMockBuilder(TaxDetailsItemInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $quoteItem->expects($this->once())->method('setCustomPrice'); + + $this->commonTaxCollector->updateItemTaxInfo( + $quoteItem, + $itemTaxDetails, + $baseItemTaxDetails, + $this->store + ); + } + + /** + * Data for testGetShippingDataObject + * * @return array */ - public function getShippingDataObjectDataProvider() + public function getShippingDataObjectDataProvider(): array { $data = [ 'free_shipping' => [ diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php index bd505fd4db035..0ae021b4e9036 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php @@ -9,8 +9,12 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Tax\Model\Config; use Magento\Tax\Model\Calculation; +use Magento\Quote\Model\Quote\Item\Updater; +use \Magento\Catalog\Api\ProductRepositoryInterface; /** + * Setup utility for quote + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SetupUtil @@ -666,7 +670,18 @@ public function setupQuote($quoteData) $quote = $this->createQuote($quoteData, $customer); $this->addProductToQuote($quote, $quoteData['items']); - + if (isset($quoteData['update_items'])) { + $updater = $this->objectManager->get(Updater::class); + $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + foreach ($quoteData['update_items'] as $sku => $updateItem) { + $product = $productRepository->get($sku); + $quoteItem = $quote->getItemByProduct($product); + $updater->update( + $quoteItem, + $updateItem + ); + } + } //Set shipping amount if (isset($quoteData['shipping_method'])) { $quote->getShippingAddress()->setShippingMethod($quoteData['shipping_method']); diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_with_custom_price.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_with_custom_price.php new file mode 100644 index 0000000000000..584b356beb53b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_with_custom_price.php @@ -0,0 +1,93 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Tax\Model\Config; +use Magento\Tax\Model\Sales\Total\Quote\SetupUtil; + +$taxCalculationData['including_tax_with_custom_price'] = [ + 'config_data' => [ + SetupUtil::CONFIG_OVERRIDES => [ + Config::CONFIG_XML_PATH_PRICE_INCLUDES_TAX => 1, + Config::CONFIG_XML_PATH_APPLY_ON => 0 + ], + SetupUtil::TAX_RATE_OVERRIDES => [ + SetupUtil::TAX_RATE_TX => 8.25, + SetupUtil::TAX_STORE_RATE => 8.25, + ], + SetupUtil::TAX_RULE_OVERRIDES => [ + ], + ], + 'quote_data' => [ + 'billing_address' => [ + 'region_id' => SetupUtil::REGION_TX, + ], + 'shipping_address' => [ + 'region_id' => SetupUtil::REGION_TX, + ], + 'items' => [ + [ + 'sku' => 'simple1', + 'price' => 16.24, + 'qty' => 1, + ], + ], + 'update_items' => [ + 'simple1' => [ + 'custom_price' => 14, + 'qty' => 1, + ], + ], + ], + 'expected_results' => [ + 'address_data' => [ + 'subtotal' => 12.93, + 'base_subtotal' => 12.93, + 'subtotal_incl_tax' => 14, + 'base_subtotal_incl_tax' => 14, + 'tax_amount' => 1.07, + 'base_tax_amount' => 1.07, + 'shipping_amount' => 0, + 'base_shipping_amount' => 0, + 'shipping_incl_tax' => 0, + 'base_shipping_incl_tax' => 0, + 'shipping_taxable' => 0, + 'base_shipping_taxable' => 0, + 'shipping_tax_amount' => 0, + 'base_shipping_tax_amount' => 0, + 'discount_amount' => 0, + 'base_discount_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, + 'grand_total' => 14, + 'base_grand_total' => 14, + ], + 'items_data' => [ + 'simple1' => [ + 'row_total' => 12.93, + 'base_row_total' => 12.93, + 'tax_percent' => 8.25, + 'price' => 12.93, + 'custom_price' => 12.93, + 'original_custom_price' => 14, + 'base_price' => 12.93, + 'price_incl_tax' => 14, + 'base_price_incl_tax' => 14, + 'row_total_incl_tax' => 14, + 'base_row_total_incl_tax' => 14, + 'tax_amount' => 1.07, + 'base_tax_amount' => 1.07, + 'discount_amount' => 0, + 'base_discount_amount' => 0, + 'discount_percent' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + ], + ], + ], +]; diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php b/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php index f22b48a259685..cdc3b7d135d1d 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); /** * Global array that holds test scenarios data @@ -31,3 +32,4 @@ require_once __DIR__ . '/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_row.php'; require_once __DIR__ . '/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_total.php'; require_once __DIR__ . '/scenarios/including_tax_apply_tax_after_discount.php'; +require_once __DIR__ . '/scenarios/including_tax_with_custom_price.php'; From 8fa7af56d43bd1657534a31b8d0588ce06e9acde Mon Sep 17 00:00:00 2001 From: Davit_Zakharyan <davit_zakharyan@epam.com> Date: Fri, 29 Mar 2019 17:50:32 +0400 Subject: [PATCH 261/603] MAGETWO-58764: [GitHub] Minimal Query Length For Catalog Search #6681 - Updated automated test script. --- .../AdminSetMinimalQueryLengthActionGroup.xml | 1 + .../Test/Mftf/Data/CatalogSearchData.xml | 27 ++++++++++++++++ .../Mftf/Data/MinMaxQueryLengthHintsData.xml | 0 .../Mftf/Metadata/catalog_search-meta.xml | 32 +++++++++++++++++++ .../CatalogSearchAdminConfigSection.xml | 17 ++++++++++ ...MinimalQueryLengthForCatalogSearchTest.xml | 6 ++-- .../CatalogSearchAdminConfigSection.xml | 4 --- 7 files changed, 81 insertions(+), 6 deletions(-) rename app/code/Magento/{Config => CatalogSearch}/Test/Mftf/ActionGroup/AdminSetMinimalQueryLengthActionGroup.xml (93%) create mode 100644 app/code/Magento/CatalogSearch/Test/Mftf/Data/CatalogSearchData.xml rename app/code/Magento/{Config => CatalogSearch}/Test/Mftf/Data/MinMaxQueryLengthHintsData.xml (100%) create mode 100644 app/code/Magento/CatalogSearch/Test/Mftf/Metadata/catalog_search-meta.xml create mode 100644 app/code/Magento/CatalogSearch/Test/Mftf/Section/CatalogSearchAdminConfigSection.xml rename app/code/Magento/{Search => CatalogSearch}/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml (86%) diff --git a/app/code/Magento/Config/Test/Mftf/ActionGroup/AdminSetMinimalQueryLengthActionGroup.xml b/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/AdminSetMinimalQueryLengthActionGroup.xml similarity index 93% rename from app/code/Magento/Config/Test/Mftf/ActionGroup/AdminSetMinimalQueryLengthActionGroup.xml rename to app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/AdminSetMinimalQueryLengthActionGroup.xml index b9ef37cb4effe..e60be3729834a 100644 --- a/app/code/Magento/Config/Test/Mftf/ActionGroup/AdminSetMinimalQueryLengthActionGroup.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/AdminSetMinimalQueryLengthActionGroup.xml @@ -21,6 +21,7 @@ <see userInput="{{MinMaxQueryLength.Hint}}" selector="{{AdminCatalogSearchConfigurationSection.maxQueryLengthHint}}" stepKey="seeHint2"/> <uncheckOption selector="{{AdminCatalogSearchConfigurationSection.minQueryLengthInherit}}" stepKey="uncheckSystemValue"/> <fillField selector="{{AdminCatalogSearchConfigurationSection.minQueryLength}}" userInput="{{minLength}}" stepKey="setMinQueryLength"/> + <scrollTo selector="{{AdminConfigCatalogCategoryPermissionsSection.catalogPermissionsTab}}" stepKey="scrollToCatalogPermissionsTab"/> <click selector="{{AdminCatalogSearchConfigurationSection.catalogSearchTab}}" stepKey="collapseTab"/> <click selector="{{ContentManagementSection.Save}}" stepKey="saveConfig"/> <waitForPageLoad stepKey="waitForConfigSaved"/> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Data/CatalogSearchData.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Data/CatalogSearchData.xml new file mode 100644 index 0000000000000..6868456079110 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Data/CatalogSearchData.xml @@ -0,0 +1,27 @@ +<?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="SetMinQueryLengthToDefault" type="catalog_search_config_def"> + <requiredEntity type="enable">DefaultMinQueryLength</requiredEntity> + </entity> + <entity name="UncheckMinQueryLengthAndSet" type="catalog_search_config_query_length"> + <requiredEntity type="number">SetMinQueryLengthToOne</requiredEntity> + </entity> + <entity name="DefaultMinQueryLength" type="enable"> + <data key="inherit">true</data> + </entity> + <entity name="DefaultMinQueryLengthDisable" type="enable"> + <data key="inherit">0</data> + </entity> + <entity name="SetMinQueryLengthToOne" type="number"> + <data key="value">1</data> + </entity> + +</entities> \ No newline at end of file diff --git a/app/code/Magento/Config/Test/Mftf/Data/MinMaxQueryLengthHintsData.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Data/MinMaxQueryLengthHintsData.xml similarity index 100% rename from app/code/Magento/Config/Test/Mftf/Data/MinMaxQueryLengthHintsData.xml rename to app/code/Magento/CatalogSearch/Test/Mftf/Data/MinMaxQueryLengthHintsData.xml diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Metadata/catalog_search-meta.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Metadata/catalog_search-meta.xml new file mode 100644 index 0000000000000..7405377249aa4 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Metadata/catalog_search-meta.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataOperation.xsd"> + <operation name="CatalogSearchConfigDefault" dataType="catalog_search_config_def" type="create" auth="adminFormKey" url="/admin/system_config/save/section/catalog/" method="POST"> + <object key="groups" dataType="catalog_search_config_def"> + <object key="search" dataType="catalog_search_config_def"> + <object key="fields" dataType="catalog_search_config_def"> + <object key="min_query_length" dataType="enable"> + <field key="inherit">boolean</field> + </object> + </object> + </object> + </object> + </operation> + <operation name="CatalogSearchConfigQueryLength" dataType="catalog_search_config_query_length" type="create" auth="adminFormKey" url="/admin/system_config/save/section/catalog/" method="POST"> + <object key="groups" dataType="catalog_search_config_query_length"> + <object key="search" dataType="catalog_search_config_query_length"> + <object key="fields" dataType="catalog_search_config_query_length"> + <object key="min_query_length" dataType="number"> + <field key="value">integer</field> + </object> + </object> + </object> + </object> + </operation> +</operations> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Section/CatalogSearchAdminConfigSection.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Section/CatalogSearchAdminConfigSection.xml new file mode 100644 index 0000000000000..605bcabb8a81d --- /dev/null +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Section/CatalogSearchAdminConfigSection.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminCatalogSearchConfigurationSection"> + <element name="minQueryLength" type="input" selector="#catalog_search_min_query_length"/> + <element name="minQueryLengthInherit" type="checkbox" selector="#catalog_search_min_query_length_inherit"/> + <element name="minQueryLengthHint" type="text" selector="#row_catalog_search_min_query_length .value span"/> + <element name="maxQueryLengthHint" type="text" selector="#row_catalog_search_max_query_length .value span"/> + </section> +</sections> \ No newline at end of file diff --git a/app/code/Magento/Search/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml similarity index 86% rename from app/code/Magento/Search/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml rename to app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml index 2736b3d67474f..9ca7614ed166b 100644 --- a/app/code/Magento/Search/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml @@ -10,13 +10,13 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="MinimalQueryLengthForCatalogSearchTest"> <annotations> - <features value="Catalog"/> + <features value="CatalogSearch"/> <title value="Minimal query length for catalog search"/> <description value="Minimal query length for catalog search"/> <severity value="AVERAGE"/> <testCaseId value="MC-6325"/> <useCaseId value="MAGETWO-58764"/> - <group value="Catalog"/> + <group value="CatalogSearch"/> </annotations> <before> <createData entity="ApiCategory" stepKey="createCategory"/> @@ -28,9 +28,11 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <createData entity="SetMinQueryLengthToDefault" stepKey="setMinimumQueryLengthToDefault"/> <actionGroup ref="logout" stepKey="logout"/> </after> <actionGroup ref="SetMinimalQueryLengthActionGroup" stepKey="setMinQueryLength"/> + <comment userInput="go to Storefront and search for product" stepKey="searchProdUsingMinQueryLength"/> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToHomePage"/> <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="s" stepKey="fillAttribute"/> <waitForPageLoad stepKey="waitForSearchTextBox"/> diff --git a/app/code/Magento/Config/Test/Mftf/Section/CatalogSearchAdminConfigSection.xml b/app/code/Magento/Config/Test/Mftf/Section/CatalogSearchAdminConfigSection.xml index ab9fb55c2c9d5..e82ad4670f9b3 100644 --- a/app/code/Magento/Config/Test/Mftf/Section/CatalogSearchAdminConfigSection.xml +++ b/app/code/Magento/Config/Test/Mftf/Section/CatalogSearchAdminConfigSection.xml @@ -11,9 +11,5 @@ <element name="checkIfCatalogSearchTabExpand" type="button" selector="#catalog_search-head:not(.open)"/> <element name="searchEngineDefaultSystemValue" type="checkbox" selector="#catalog_search_engine_inherit"/> <element name="searchEngine" type="select" selector="#catalog_search_engine"/> - <element name="minQueryLength" type="input" selector="#catalog_search_min_query_length"/> - <element name="minQueryLengthInherit" type="checkbox" selector="#catalog_search_min_query_length_inherit"/> - <element name="minQueryLengthHint" type="text" selector="#row_catalog_search_min_query_length .value span"/> - <element name="maxQueryLengthHint" type="text" selector="#row_catalog_search_max_query_length .value span"/> </section> </sections> \ No newline at end of file From e71d8e80c7373ac5adcc6a0b97cfd5ca17761233 Mon Sep 17 00:00:00 2001 From: Veronika Kurochkina <veronika_kurochkina@epam.com> Date: Fri, 29 Mar 2019 16:58:11 +0300 Subject: [PATCH 262/603] MAGETWO-65232: Product name does not display special characters properly - Updated automated test script. --- .../Test/Mftf/Test/AdminRemoveImageAffectsAllScopesTest.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageAffectsAllScopesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageAffectsAllScopesTest.xml index 060720ab007eb..85c54e0942c74 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageAffectsAllScopesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageAffectsAllScopesTest.xml @@ -65,6 +65,10 @@ </actionGroup> <deleteData createDataKey="category" stepKey="deletePreReqCategory"/> <deleteData createDataKey="product" stepKey="deleteFirstProduct"/> + + <magentoCLI stepKey="reindex" command="indexer:reindex"/> + <magentoCLI stepKey="flushCache" command="cache:flush"/> + <actionGroup ref="logout" stepKey="logout"/> </after> From 503ab39f9cfbc0a71b99ca5a98d67cb1955f1f73 Mon Sep 17 00:00:00 2001 From: serhii balko <serhii.balko@transoftgroup.com> Date: Fri, 29 Mar 2019 16:13:03 +0200 Subject: [PATCH 263/603] MAGETWO-98603: [2.3] Fixed Tier Pricing for Bundle items doesn't work --- .../Mftf/Section/StorefrontBundledSection.xml | 3 + ...rontCheckBundleProductOptionTierPrices.xml | 150 ++++++++++++++++++ .../DataProviders/OptionPriceRendererTest.php | 73 +++++++++ .../view/type/bundle/option/checkbox.phtml | 4 +- .../view/type/bundle/option/radio.phtml | 4 +- .../view/type/bundle/option/select.phtml | 9 +- .../product_with_simple_tier_pricing.php | 9 +- 7 files changed, 240 insertions(+), 12 deletions(-) create mode 100644 app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml create mode 100644 app/code/Magento/Bundle/Test/Unit/Block/DataProviders/OptionPriceRendererTest.php diff --git a/app/code/Magento/Bundle/Test/Mftf/Section/StorefrontBundledSection.xml b/app/code/Magento/Bundle/Test/Mftf/Section/StorefrontBundledSection.xml index dbe48c46c820b..30a7e8b777f3b 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Section/StorefrontBundledSection.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Section/StorefrontBundledSection.xml @@ -26,11 +26,14 @@ <element name="bundleProductName" type="text" selector="//*[@id='maincontent']//span[@itemprop='name']"/> <element name="pageNotFound" type="text" selector="//h1[@class='page-title']//span[contains(., 'Whoops, our bad...')]"/> <element name="dropDownOptionOneProducts" type="select" selector="//label//span[contains(text(), '{{productName}}')]/../..//div[@class='control']//select" parameterized="true"/> + <element name="dropDownOptionTierPrices" type="text" selector="//label//span[contains(text(), '{{optionName}}')]/../..//div[@class='control']//div[@class='option-tier-prices']" parameterized="true"/> <element name="productInBundle" type="select" selector="//label//span[contains(text(), '{{productName}}')]" parameterized="true"/> <element name="dropDownOptionOneQuantity" type="input" selector="//span[contains(text(), '{{productName}}')]/../..//input" parameterized="true"/> <element name="radioButtonOptionTwoProducts" type="checkbox" selector="//label//span[contains(text(), '{{productName}}')]/../..//div[@class='control']//div[@class='field choice'][{{productNumber}}]/input" parameterized="true"/> <element name="radioButtonOptionTwoQuantity" type="input" selector="//label//span[contains(text(), '{{productName}}')]/../..//div[@class='control']//div[@class='field qty qty-holder']//input" parameterized="true"/> + <element name="radioButtonOptionLabel" type="text" selector="//label//span[contains(text(), '{{optionName}}')]/../..//div[@class='control']//div[@class='field choice']//label[contains(.,'{{productName}}')]" parameterized="true"/> <element name="checkboxOptionThreeProducts" type="checkbox" selector="//label//span[contains(text(), '{{productName}}')]/../..//div[@class='control']//div[@class='field choice'][{{productNumber}}]/input" parameterized="true"/> + <element name="checkboxOptionLabel" type="text" selector="//label//span[contains(text(), '{{optionName}}')]/../..//div[@class='control']//div[@class='field choice']//label[contains(.,'{{productName}}')]" parameterized="true"/> <element name="multiselectOptionFourProducts" type="multiselect" selector="//label//span[contains(text(), '{{productName}}')]/../..//select[@multiple='multiple']" parameterized="true"/> <element name="currencyTrigger" type="select" selector="#switcher-currency-trigger" timeout="30"/> <element name="currency" type="select" selector="//a[text()='{{arg}}']" parameterized="true"/> diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml new file mode 100644 index 0000000000000..23d70c978ecd8 --- /dev/null +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml @@ -0,0 +1,150 @@ +<?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="StorefrontCheckBundleProductOptionTierPrices"> + <annotations> + <features value="Bundle"/> + <stories value="View bundle products"/> + <title value="Check tier prices for bundle options"/> + <testCaseId value="MAGETWO-98968"/> + <group value="bundle"/> + </annotations> + <before> + <!-- Create simple products --> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"> + <field key="price">10</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"> + <field key="price">20</field> + </createData> + + <!-- Add tier prices to simple products --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <amOnPage url="{{AdminProductEditPage.url($$simpleProduct1.id$$)}}" stepKey="openAdminEditPageProduct1"/> + <actionGroup ref="ProductSetAdvancedPricing" stepKey="addTierPriceProduct1"> + <argument name="group" value="ALL GROUPS"/> + <argument name="quantity" value="5"/> + <argument name="price" value="Discount"/> + <argument name="amount" value="50"/> + </actionGroup> + + <amOnPage url="{{AdminProductEditPage.url($$simpleProduct2.id$$)}}" stepKey="openAdminEditPageProduct2"/> + <actionGroup ref="ProductSetAdvancedPricing" stepKey="addTierPriceProduct2"> + <argument name="group" value="ALL GROUPS"/> + <argument name="quantity" value="7"/> + <argument name="price" value="Discount"/> + <argument name="amount" value="25"/> + </actionGroup> + + <!-- Create Bundle product --> + <createData entity="ApiBundleProduct" stepKey="createBundleProduct"/> + <createData entity="DropDownBundleOption" stepKey="createDropDownBundleOption"> + <requiredEntity createDataKey="createBundleProduct"/> + <field key="title">Drop-down Option</field> + </createData> + <createData entity="RadioButtonsOption" stepKey="createBundleRadioButtonsOption"> + <requiredEntity createDataKey="createBundleProduct"/> + <field key="title">Radio Buttons Option</field> + </createData> + <createData entity="CheckboxOption" stepKey="createBundleCheckboxOption"> + <requiredEntity createDataKey="createBundleProduct"/> + <field key="title">Checkbox Option</field> + </createData> + <createData entity="ApiBundleLink" stepKey="linkCheckboxOptionToProduct1"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleCheckboxOption"/> + <requiredEntity createDataKey="simpleProduct1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkCheckboxOptionToProduct2"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleCheckboxOption"/> + <requiredEntity createDataKey="simpleProduct2"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkDropDownOptionToProduct1"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createDropDownBundleOption"/> + <requiredEntity createDataKey="simpleProduct1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkDropDownOptionToProduct2"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createDropDownBundleOption"/> + <requiredEntity createDataKey="simpleProduct2"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkRadioButtonsOptionToProduct1"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleRadioButtonsOption"/> + <requiredEntity createDataKey="simpleProduct1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkRadioButtonsOptionToProduct2"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleRadioButtonsOption"/> + <requiredEntity createDataKey="simpleProduct2"/> + </createData> + + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + </before> + <after> + <deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteSimpleProduct2"/> + <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> + </after> + + <!-- Go to storefront product page --> + <amOnPage url="{{StorefrontProductPage.url($$createBundleProduct.custom_attributes[url_key]$$)}}" stepKey="onPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <click selector="{{StorefrontBundledSection.addToCart}}" stepKey="clickCustomize"/> + + <!--"Drop-down" type option--> + <!-- Check Tier Prices for product 1 --> + <selectOption selector="{{StorefrontBundledSection.dropDownOptionOneProducts('Drop-down Option')}}" userInput="$$simpleProduct1.sku$$ +$$$simpleProduct1.price$$.00" stepKey="selectDropDownOptionProduct1"/> + <seeOptionIsSelected selector="{{StorefrontBundledSection.dropDownOptionOneProducts('Drop-down Option')}}" userInput="$$simpleProduct1.sku$$ +$$$simpleProduct1.price$$.00" stepKey="checkDropDownOptionProduct1"/> + <grabTextFrom selector="{{StorefrontBundledSection.dropDownOptionTierPrices('Drop-down Option')}}" stepKey="DropDownTierPriceTextProduct1"/> + <assertContains stepKey="assertDropDownTierPriceTextProduct1"> + <expectedResult type="string">Buy 5 for $5.00 each and save 50%</expectedResult> + <actualResult type="variable">DropDownTierPriceTextProduct1</actualResult> + </assertContains> + <!-- Check Tier Prices for product 2 --> + <selectOption selector="{{StorefrontBundledSection.dropDownOptionOneProducts('Drop-down Option')}}" userInput="$$simpleProduct2.sku$$ +$$$simpleProduct2.price$$.00" stepKey="selectDropDownOptionProduct2"/> + <seeOptionIsSelected selector="{{StorefrontBundledSection.dropDownOptionOneProducts('Drop-down Option')}}" userInput="$$simpleProduct2.sku$$ +$$$simpleProduct2.price$$.00" stepKey="checkDropDownOptionProduct2"/> + <grabTextFrom selector="{{StorefrontBundledSection.dropDownOptionTierPrices('Drop-down Option')}}" stepKey="DropDownTierPriceTextProduct2"/> + <assertContains stepKey="assertDropDownTierPriceTextProduct2"> + <expectedResult type="string">Buy 7 for $15.00 each and save 25%</expectedResult> + <actualResult type="variable">DropDownTierPriceTextProduct2</actualResult> + </assertContains> + + <!--"Radio Buttons" type option--> + <!-- Check Tier Prices for product 1 --> + <grabTextFrom selector="{{StorefrontBundledSection.radioButtonOptionLabel('Radio Buttons Option', '$$simpleProduct1.sku$$')}}" stepKey="RadioButtonsOptionTierPriceTextProduct1"/> + <assertContains stepKey="assertRadioButtonsOptionTierPriceTextProduct1"> + <expectedResult type="string">Buy 5 for $5.00 each and save 50%</expectedResult> + <actualResult type="variable">RadioButtonsOptionTierPriceTextProduct1</actualResult> + </assertContains> + <!-- Check Tier Prices for product 2 --> + <grabTextFrom selector="{{StorefrontBundledSection.radioButtonOptionLabel('Radio Buttons Option', '$$simpleProduct2.sku$$')}}" stepKey="RadioButtonsOptionTierPriceTextProduct2"/> + <assertContains stepKey="assertRadioButtonsOptionTierPriceTextProduct2"> + <expectedResult type="string">Buy 7 for $15.00 each and save 25%</expectedResult> + <actualResult type="variable">RadioButtonsOptionTierPriceTextProduct2</actualResult> + </assertContains> + + <!--"Checkbox" type option--> + <!-- Check Tier Prices for product 1 --> + <grabTextFrom selector="{{StorefrontBundledSection.checkboxOptionLabel('Checkbox Option', '$$simpleProduct1.sku$$')}}" stepKey="CheckBoxOptionTierPriceTextProduct1"/> + <assertContains stepKey="assertCheckBoxOptionTierPriceTextProduct1"> + <expectedResult type="string">Buy 5 for $5.00 each and save 50%</expectedResult> + <actualResult type="variable">CheckBoxOptionTierPriceTextProduct1</actualResult> + </assertContains> + <!-- Check Tier Prices for product 2 --> + <grabTextFrom selector="{{StorefrontBundledSection.checkboxOptionLabel('Checkbox Option', '$$simpleProduct2.sku$$')}}" stepKey="CheckBoxOptionTierPriceTextProduct2"/> + <assertContains stepKey="assertCheckBoxOptionTierPriceTextProduct2"> + <expectedResult type="string">Buy 7 for $15.00 each and save 25%</expectedResult> + <actualResult type="variable">CheckBoxOptionTierPriceTextProduct2</actualResult> + </assertContains> + </test> +</tests> diff --git a/app/code/Magento/Bundle/Test/Unit/Block/DataProviders/OptionPriceRendererTest.php b/app/code/Magento/Bundle/Test/Unit/Block/DataProviders/OptionPriceRendererTest.php new file mode 100644 index 0000000000000..657803fbb3e2b --- /dev/null +++ b/app/code/Magento/Bundle/Test/Unit/Block/DataProviders/OptionPriceRendererTest.php @@ -0,0 +1,73 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Test\Unit\Block\DataProviders; + +use Magento\Bundle\Block\DataProviders\OptionPriceRenderer; +use Magento\Catalog\Model\Product; +use Magento\Framework\Pricing\Render; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\View\Element\BlockInterface; +use Magento\Framework\View\LayoutInterface; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Class to test additional data for bundle options + */ +class OptionPriceRendererTest extends TestCase +{ + /** + * @var LayoutInterface|MockObject + */ + private $layoutMock; + + /** + * @var OptionPriceRenderer + */ + private $renderer; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = new ObjectManager($this); + + $this->layoutMock = $this->createMock( + LayoutInterface::class + ); + + $this->renderer = $objectManager->getObject( + OptionPriceRenderer::class, + ['layout' => $this->layoutMock] + ); + } + + public function testRenderTierPrice() + { + $tierPriceHtml = 'tier price html'; + $expectedArguments = ['zone' => Render::ZONE_ITEM_OPTION]; + + $productMock = $this->createMock(Product::class); + $blockMock = $this->createPartialMock(BlockInterface::class, ['toHtml', 'render']); + $blockMock->expects($this->once()) + ->method('render') + ->with('tier_price', $productMock, $expectedArguments) + ->willReturn($tierPriceHtml); + + $this->layoutMock->method('getBlock') + ->with('product.price.render.default') + ->willReturn($blockMock); + + $this->assertEquals( + $tierPriceHtml, + $this->renderer->renderTierPrice($productMock), + 'Render Tier price is wrong' + ); + } +} diff --git a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/checkbox.phtml b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/checkbox.phtml index ad1843890eb4a..830d03c826f32 100644 --- a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/checkbox.phtml +++ b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/checkbox.phtml @@ -19,7 +19,7 @@ <div class="nested options-list"> <?php if ($block->showSingle()): ?> <?= /* @escapeNotVerified */ $block->getSelectionQtyTitlePrice($_selections[0]) ?> - <?= /* @escapeNotVerified */ $block->getTierPriceRenderer()->renderTierPrice($_selections[0]) ?> + <?= /* @noEscape */ $block->getTierPriceRenderer()->renderTierPrice($_selections[0]) ?> <input type="hidden" class="bundle-option-<?= /* @escapeNotVerified */ $_option->getId() ?> product bundle option" name="bundle_option[<?= /* @escapeNotVerified */ $_option->getId() ?>]" @@ -40,7 +40,7 @@ for="bundle-option-<?= /* @escapeNotVerified */ $_option->getId() ?>-<?= /* @escapeNotVerified */ $_selection->getSelectionId() ?>"> <span><?= /* @escapeNotVerified */ $block->getSelectionQtyTitlePrice($_selection) ?></span> <br/> - <?= /* @escapeNotVerified */ $block->getTierPriceRenderer()->renderTierPrice($_selection) ?> + <?= /* @noEscape */ $block->getTierPriceRenderer()->renderTierPrice($_selection) ?> </label> </div> <?php endforeach; ?> diff --git a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/radio.phtml b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/radio.phtml index cd4af99cbc60f..1f33d97227ea3 100644 --- a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/radio.phtml +++ b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/radio.phtml @@ -21,7 +21,7 @@ <div class="nested options-list"> <?php if ($block->showSingle()): ?> <?= /* @escapeNotVerified */ $block->getSelectionTitlePrice($_selections[0]) ?> - <?= /* @escapeNotVerified */ $block->getTierPriceRenderer()->renderTierPrice($_selections[0]) ?> + <?= /* @noEscape */ $block->getTierPriceRenderer()->renderTierPrice($_selections[0]) ?> <input type="hidden" class="bundle-option-<?= (int)$_option->getId() ?> product bundle option" name="bundle_option[<?= (int)$_option->getId() ?>]" @@ -59,7 +59,7 @@ for="bundle-option-<?= /* @escapeNotVerified */ $_option->getId() ?>-<?= /* @escapeNotVerified */ $_selection->getSelectionId() ?>"> <span><?= /* @escapeNotVerified */ $block->getSelectionTitlePrice($_selection) ?></span> <br/> - <?= /* @escapeNotVerified */ $block->getTierPriceRenderer()->renderTierPrice($_selection) ?> + <?= /* @noEscape */ $block->getTierPriceRenderer()->renderTierPrice($_selection) ?> </label> </div> <?php endforeach; ?> diff --git a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/select.phtml b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/select.phtml index 4f718278971ae..4ea00f62b2043 100644 --- a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/select.phtml +++ b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/select.phtml @@ -20,7 +20,7 @@ <div class="control"> <?php if ($block->showSingle()): ?> <?= /* @escapeNotVerified */ $block->getSelectionTitlePrice($_selections[0]) ?> - <?= /* @escapeNotVerified */ $block->getTierPriceRenderer()->renderTierPrice($_selections[0]) ?> + <?= /* @noEscape */ $block->getTierPriceRenderer()->renderTierPrice($_selections[0]) ?> <input type="hidden" class="bundle-option-<?= /* @escapeNotVerified */ $_option->getId() ?> product bundle option" name="bundle_option[<?= /* @escapeNotVerified */ $_option->getId() ?>]" @@ -40,11 +40,12 @@ </option> <?php endforeach; ?> </select> - <div id="option-tier-prices-<?= /* @escapeNotVerified */ $_option->getId() ?>"> + <div id="option-tier-prices-<?= /* @escapeNotVerified */ $_option->getId() ?>" class="option-tier-prices"> <?php foreach ($_selections as $_selection): ?> <div data-role="selection-tier-prices" - data-selection-id="<?= /* @escapeNotVerified */ $_selection->getSelectionId() ?>"> - <?= /* @escapeNotVerified */ $block->getTierPriceRenderer()->renderTierPrice($_selection) ?> + data-selection-id="<?= /* @escapeNotVerified */ $_selection->getSelectionId() ?>" + class="selection-tier-prices"> + <?= /* @noEscape */ $block->getTierPriceRenderer()->renderTierPrice($_selection) ?> </div> <?php endforeach; ?> </div> diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php index 0342694cead93..b97c1f0208b40 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php @@ -7,7 +7,6 @@ require __DIR__ . '/../../../Magento/Catalog/_files/product_simple.php'; - /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ $productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); $simpleProduct = $productRepository->get('simple'); @@ -15,9 +14,10 @@ /** @var $product \Magento\Catalog\Model\Product */ $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); $product->setTypeId('bundle') - ->setAttributeSetId(4) + ->setAttributeSetId($product->getDefaultAttributeSetId()) ->setWebsiteIds([1]) ->setPriceType(\Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC) + ->setPriceView(1) ->setName('Bundle Product') ->setSku('bundle-product') ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) @@ -28,7 +28,8 @@ [ 'title' => 'Bundle Product Items', 'default_title' => 'Bundle Product Items', - 'type' => 'checkbox', 'required' => 1, + 'type' => 'checkbox', + 'required' => 1, 'delete' => '', ], ] @@ -36,4 +37,4 @@ ->setBundleSelectionsData( [[['product_id' => $simpleProduct->getId(), 'selection_qty' => 1, 'delete' => '']]] ); -$product->save(); +$productRepository->save($product); From 08eafb31397065fcf087ebdbaf3c9f6ea9534d62 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Fri, 29 Mar 2019 16:00:12 +0100 Subject: [PATCH 264/603] Adjusting action groups --- .../StorefrontCustomerResetPasswordActionGroup.xml | 12 ++++++++++-- .../StorefrontResetCustomerPasswordFailedTest.xml | 6 ++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerResetPasswordActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerResetPasswordActionGroup.xml index 2c641317c6e9a..f322be6109218 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerResetPasswordActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerResetPasswordActionGroup.xml @@ -11,8 +11,6 @@ <actionGroup name="StorefrontCustomerResetPasswordActionGroup"> <arguments> <argument name="email" type="string" /> - <argument name="message" type="string" defaultValue="" /> - <argument name="messageType" type="string" defaultValue="success" /> </arguments> <amOnPage stepKey="amOnSignInPage" url="{{StorefrontCustomerSignInPage.url}}"/> @@ -22,6 +20,16 @@ <fillField stepKey="fillEmailField" userInput="{{email}}" selector="{{StorefrontForgotPasswordSection.email}}"/> <click stepKey="clickResetPassword" selector="{{StorefrontForgotPasswordSection.resetMyPasswordButton}}"/> <waitForPageLoad stepKey="waitForPageLoaded" /> + </actionGroup> + + <actionGroup name="AssertCustomerResetPasswordActionGroup"> + <arguments> + <argument name="url" type="string"/> + <argument name="message" type="string" defaultValue="" /> + <argument name="messageType" type="string" defaultValue="success" /> + </arguments> + + <seeInCurrentUrl stepKey="seeInSignInPage" url="{{url}}"/> <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.messageByType(messageType)}}" stepKey="waitForMessage" /> <see stepKey="seeMessage" userInput="{{message}}" selector="{{StorefrontCustomerLoginMessagesSection.messageByType(messageType)}}"/> </actionGroup> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml index 684d0c0730c3f..56c8af118fadc 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml @@ -28,10 +28,16 @@ <actionGroup ref="StorefrontCustomerResetPasswordActionGroup" stepKey="resetPasswordFirstAttempt"> <argument name="email" value="$$customer.email$$" /> + </actionGroup> + <actionGroup ref="AssertCustomerResetPasswordActionGroup" stepKey="seePageWithSuccessMessage"> + <argument name="url" value="{{StorefrontCustomerSignInPage.url}}"/> <argument name="message" value="If there is an account associated with $$customer.email$$ you will receive an email with a link to reset your password."/> </actionGroup> <actionGroup ref="StorefrontCustomerResetPasswordActionGroup" stepKey="resetPasswordSecondAttempt"> <argument name="email" value="$$customer.email$$" /> + </actionGroup> + <actionGroup ref="AssertCustomerResetPasswordActionGroup" stepKey="seePageWithErrorMessage"> + <argument name="url" value="{{StorefrontForgotPasswordPage.url}}"/> <argument name="message" value="We received too many requests for password resets. Please wait and try again later or contact hello@example.com."/> <argument name="messageType" value="error" /> </actionGroup> From 4944b3ea74dcd9fe72586a8d8de6e93e79df77b7 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Fri, 29 Mar 2019 17:25:57 +0200 Subject: [PATCH 265/603] Updating the old test by marking the migrated variations. --- .../Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.xml index 90c42505585a2..8290d825593af 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.xml @@ -10,17 +10,20 @@ <variation name="ValidateEmailOnCheckoutTestVariation1"> <data name="customer/data/email" xsi:type="string">johndoe</data> <data name="customer/data/firstname" xsi:type="string">John</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Checkout\Test\Constraint\AssertEmailErrorValidationMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertEmailToolTips" /> </variation> <variation name="ValidateEmailOnCheckoutTestVariation2"> <data name="customer/data/email" xsi:type="string">johndoe#example.com</data> <data name="customer/data/firstname" xsi:type="string">John</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Checkout\Test\Constraint\AssertEmailErrorValidationMessage" /> </variation> <variation name="ValidateEmailOnCheckoutTestVariation3"> <data name="customer/data/email" xsi:type="string">johndoe@example.c</data> <data name="customer/data/firstname" xsi:type="string">John</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Checkout\Test\Constraint\AssertEmailErrorValidationMessage" /> </variation> </testCase> From 5b919eac8764901e1d504ccf2db1b046a91ae79c Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin <serhiy.yelahin@transoftgroup.com> Date: Fri, 29 Mar 2019 17:33:12 +0200 Subject: [PATCH 266/603] MAGETWO-98886: Gift Card Accounts: expiration date subtracts one day --- .../Framework/Data/Form/Element/DateTest.php | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/Data/Form/Element/DateTest.php b/dev/tests/integration/testsuite/Magento/Framework/Data/Form/Element/DateTest.php index a934372bfd907..a64df0451f9c0 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Data/Form/Element/DateTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Data/Form/Element/DateTest.php @@ -4,41 +4,51 @@ * See COPYING.txt for license details. */ +namespace Magento\Framework\Data\Form\Element; + +use Magento\Framework\Data\Form\ElementFactory; +use Magento\TestFramework\Helper\Bootstrap; + /** * Tests for \Magento\Framework\Data\Form\Element\Date */ -namespace Magento\Framework\Data\Form\Element; - class DateTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Framework\Data\Form\ElementFactory + * @var ElementFactory */ protected $_elementFactory; /** - * SetUp method + * @inheritdoc */ protected function setUp() { - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->_elementFactory = $objectManager->create(\Magento\Framework\Data\Form\ElementFactory::class); + $objectManager = Bootstrap::getObjectManager(); + $this->_elementFactory = $objectManager->create(ElementFactory::class); } /** + * Test get value + * + * @param array $data + * @param string $expect + * @return void * @dataProvider getValueDataProvider */ - public function testGetValue(array $data, $expect) + public function testGetValue(array $data, string $expect): void { - /** @var $date \Magento\Framework\Data\Form\Element\Date */ - $date = $this->_elementFactory->create(\Magento\Framework\Data\Form\Element\Date::class, $data); + /** @var $date Date */ + $date = $this->_elementFactory->create(Date::class, $data); $this->assertEquals($expect, $date->getValue()); } /** + * Get value test data provider + * * @return array */ - public function getValueDataProvider() + public function getValueDataProvider(): array { $testTimestamp = strtotime('2014-05-18 12:08:16'); $date = new \DateTime('@' . $testTimestamp); @@ -56,15 +66,22 @@ public function getValueDataProvider() 'time_format' => 'h:mm a', 'value' => $testTimestamp, ], - $date->format('g:i A') + $date->format('g:i A'), ], [ [ 'date_format' => 'MM/d/yy', 'value' => $testTimestamp, ], - $date->format('m/j/y') - ] + $date->format('m/j/y'), + ], + [ + [ + 'date_format' => 'd-MM-Y', + 'value' => $date->format('d-m-Y'), + ], + $date->format('d-m-Y'), + ], ]; } } From fd611a7b4978d11e3ca5ad062224c19bf0830894 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Fri, 29 Mar 2019 17:56:39 +0200 Subject: [PATCH 267/603] MAGETWO-70996: [GitHub] Customer Address "default billing address" Attribute Not Used in Checkout #8777 # Conflicts: # app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml # app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml # app/code/Magento/Checkout/Test/Mftf/Test/DefaultBillingAddressShouldBeCheckedOnPaymentPageTest.xml # app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml # app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js --- .../Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml | 1 - .../Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml | 3 ++- .../Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml | 3 +-- .../Checkout/Test/TestStep/FillBillingInformationStep.php | 4 +++- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml b/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml index d701993be2c4c..f066c88b12fcc 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml @@ -87,7 +87,6 @@ <waitForPageLoad stepKey="waitForPageLoad10"/> <click selector="{{BraintreeConfigurationPaymentSection.paymentMethod}}" stepKey="SelectBraintreePaymentMethod1"/> <waitForPageLoad stepKey="waitForPageLoad11"/> - <waitForPageLoad stepKey="waitForPageLoad12"/> <!--Place order--> <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="PlaceOrder1"/> <waitForPageLoad stepKey="waitForPageLoad13"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml index 7acfc14111b6f..7f9ba744507bb 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml @@ -54,6 +54,7 @@ <element name="addressBook" type="button" selector="//a[text()='Address Book']"/> <element name="noQuotes" type="text" selector=".no-quotes-block"/> <element name="paymentMethodByName" type="text" selector="//*[@id='checkout-payment-method-load']//*[contains(@class, 'payment-group')]//label[normalize-space(.)='{{var1}}']" parameterized="true"/> - <element name="billingAddressSelect" type="select" selector="select[name='billing_address_id']"/> + <element name="billingAddressSelect" type="select" selector=".payment-method._active select[name='billing_address_id']"/> + <element name="billingAddressSelectShared" type="select" selector=".checkout-billing-address select[name='billing_address_id']"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml index 13b7be6e3c411..fadc9ec50ad8d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml @@ -256,8 +256,7 @@ <!-- Fill UK Address and verify that payment available and checkout successful --> <uncheckOption selector="{{StorefrontCheckoutPaymentMethodSection.billingAddressSameAsShippingShared}}" stepKey="uncheckBillingAddressSameAsShippingCheckCheckBox"/> - <click selector="{{CheckoutShippingSection.addressDropdown}}" stepKey="clickOnAddressDropDown"/> - <selectOption selector="{{CheckoutPaymentSection.billingAddressSelect}}" userInput="New Address" stepKey="clickOnNewAddress"/> + <selectOption selector="{{CheckoutPaymentSection.billingAddressSelectShared}}" userInput="New Address" stepKey="clickOnNewAddress"/> <waitForPageLoad stepKey="waitNewAddressBillingForm"/> <actionGroup ref="LoggedInCheckoutFillNewBillingAddressActionGroup" stepKey="changeAddress"> <argument name="Address" value="updateCustomerUKAddress"/> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php index cf2f99a78cefb..b7a4c17537539 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php @@ -170,7 +170,9 @@ public function run() */ private function getDefaultBillingAddress() { - $addresses = $this->customer->getDataFieldConfig('address')['source']->getAddresses(); + $addresses = $this->customer->hasData('address') + ? $this->customer->getDataFieldConfig('address')['source']->getAddress() + : []; $defaultAddress = null; foreach ($addresses as $address) { if ($address->getDefaultBilling() === 'Yes') { From 86573396f983df625bd7bd564f251f05baf73459 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Fri, 29 Mar 2019 18:04:15 +0200 Subject: [PATCH 268/603] MAGETWO-70996: [GitHub] Customer Address "default billing address" Attribute Not Used in Checkout #8777 --- .../Checkout/Test/TestStep/FillBillingInformationStep.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php index b7a4c17537539..52b296c2e01fa 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php @@ -171,7 +171,7 @@ public function run() private function getDefaultBillingAddress() { $addresses = $this->customer->hasData('address') - ? $this->customer->getDataFieldConfig('address')['source']->getAddress() + ? $this->customer->getDataFieldConfig('address')['source']->getAddresses() : []; $defaultAddress = null; foreach ($addresses as $address) { From a5635a267e2927450518e2b8ff174df1c564b768 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Fri, 29 Mar 2019 11:31:11 -0500 Subject: [PATCH 269/603] MAGETWO-93628: Shopping cart is emptied after reset password procedure --- app/code/Magento/Customer/Model/AccountManagement.php | 4 ++-- .../Customer/Test/Unit/Model/AccountManagementTest.php | 4 +++- lib/internal/Magento/Framework/Session/SessionManager.php | 1 - 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 673300369fe06..d86286bc2fcb9 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -624,7 +624,6 @@ public function initiatePasswordReset($email, $template, $websiteId = null) * @param string $rpToken * @throws ExpiredException * @throws NoSuchEntityException - * * @return CustomerInterface * @throws LocalizedException */ @@ -703,7 +702,7 @@ public function resetPassword($email, $resetToken, $newPassword) $customerSecure->setRpTokenCreatedAt(null); $customerSecure->setPasswordHash($this->createPasswordHash($newPassword)); $this->destroyCustomerSessions($customer->getId()); - $this->sessionManager->destroy(); + $this->sessionManager->destroy(['send_expire_cookie' => false]); $this->customerRepository->save($customer); return true; @@ -1564,6 +1563,7 @@ private function getEmailNotification() /** * Destroy all active customer sessions by customer id (current session will not be destroyed). + * * Customer sessions which should be deleted are collecting from the "customer_visitor" table considering * configured session lifetime. * diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 22c9d90c086dc..aa901e8a2e978 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -1610,7 +1610,9 @@ function ($string) { $this->customerSecure->expects($this->once())->method('setRpTokenCreatedAt')->with(null); $this->customerSecure->expects($this->any())->method('setPasswordHash')->willReturn(null); - $this->sessionManager->expects($this->atLeastOnce())->method('destroy'); + $this->sessionManager->expects($this->once()) + ->method('destroy') + ->with(['send_expire_cookie' => false]); $this->sessionManager->expects($this->atLeastOnce())->method('getSessionId'); $visitor = $this->getMockBuilder(\Magento\Customer\Model\Visitor::class) ->disableOriginalConstructor() diff --git a/lib/internal/Magento/Framework/Session/SessionManager.php b/lib/internal/Magento/Framework/Session/SessionManager.php index c7d201676b228..b306b879b7127 100644 --- a/lib/internal/Magento/Framework/Session/SessionManager.php +++ b/lib/internal/Magento/Framework/Session/SessionManager.php @@ -353,7 +353,6 @@ public function destroy(array $options = null) } session_regenerate_id(true); - session_destroy(); if ($options['send_expire_cookie']) { $this->expireSessionCookie(); } From 26974e1f727e83bec7a92ce7e9b54c9e23de1c9d Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 29 Mar 2019 11:43:26 -0500 Subject: [PATCH 270/603] 229: [GraphQL caching] Add support for queries via HTTP GET --- .../Magento/GraphQl/Controller/GraphQl.php | 5 ++- .../TestCase/GraphQlAbstract.php | 7 ++-- .../TestModule/GraphQlMutationTest.php | 6 ++-- .../Controller/GraphQlControllerTest.php | 35 +++++++++---------- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/app/code/Magento/GraphQl/Controller/GraphQl.php b/app/code/Magento/GraphQl/Controller/GraphQl.php index abbe0e093c79c..6c37a5709a0bd 100644 --- a/app/code/Magento/GraphQl/Controller/GraphQl.php +++ b/app/code/Magento/GraphQl/Controller/GraphQl.php @@ -12,6 +12,7 @@ use Magento\Framework\App\RequestInterface; use Magento\Framework\App\ResponseInterface; use Magento\Framework\GraphQl\Exception\ExceptionFormatter; +use Magento\Framework\GraphQl\Exception\GraphQlRequestException; use Magento\Framework\GraphQl\Query\QueryProcessor; use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; use Magento\Framework\GraphQl\Schema\SchemaGeneratorInterface; @@ -23,6 +24,7 @@ * Front controller for web API GraphQL area. * * @api + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class GraphQl implements FrontControllerInterface { @@ -125,8 +127,9 @@ public function dispatch(RequestInterface $request) : ResponseInterface isset($data['variables']) ? $data['variables'] : [] ); } else { + $errorMessage = __('Mutation requests allowed only for POST requests'); $result['errors'] = [ - __('Mutation requests allowed only for POST requests') + $this->graphQlError->create(new GraphQlRequestException($errorMessage)) ]; $statusCode = ExceptionFormatter::HTTP_GRAPH_QL_SCHEMA_ERROR_STATUS; } diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php index f55b981a04a94..d1a6356d78fba 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php @@ -6,6 +6,7 @@ namespace Magento\TestFramework\TestCase; use Magento\TestFramework\Helper\Bootstrap; +use Magento\Framework\App\Request\Http; /** * Test case for Web API functional tests for Graphql. @@ -43,16 +44,16 @@ public function graphQlQuery( array $variables = [], string $operationName = '', array $headers = [], - string $requestType = 'POST' + string $requestType = Http::METHOD_POST ) { - if ($requestType === 'POST') { + if ($requestType === Http::METHOD_POST) { $response = $this->getGraphQlClient()->postQuery( $query, $variables, $operationName, $this->composeHeaders($headers) ); - } elseif ($requestType === 'GET') { + } elseif ($requestType === Http::METHOD_GET) { $response = $this->getGraphQlClient()->getQuery( $query, $variables, diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlMutationTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlMutationTest.php index d60281a6cf413..ef1dea1c18f54 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlMutationTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlMutationTest.php @@ -35,6 +35,10 @@ public function testMutation() $this->assertEquals([4, 5, 6], $testItem['integer_list']); } + /** + * @expectedException \Exception + * @expectedExceptionMessage Mutation requests allowed only for POST requests + */ public function testMutationIsNotAllowedViaGetRequest() { $id = 3; @@ -49,8 +53,6 @@ public function testMutationIsNotAllowedViaGetRequest() } MUTATION; - self::expectException(\Exception::class); - $this->graphQlQuery($query, [], '', [], 'GET'); } } diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php index 6e8d60a177c5d..a83e644c6e171 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php @@ -177,7 +177,8 @@ public function testMutationWithHttpGet() $response = $this->graphql->dispatch($request); $output = $this->jsonSerializer->unserialize($response->getContent()); $this->assertArrayHasKey('errors', $output); - $this->assertEquals('Mutation requests allowed only for POST requests', $output['errors'][0]); + $errorMessage = $output['errors'][0]['message']; + $this->assertEquals('Mutation requests allowed only for POST requests', $errorMessage); } /** Test request is dispatched and response generated when using GET request with parameterized query string @@ -191,19 +192,17 @@ public function testDispatchGetWithParameterizedVariables() : void /** @var ProductInterface $product */ $product = $productRepository->get('simple1'); - $query1 = <<<'QUERY' - - query GetProducts($filterInput:ProductFilterInput){ - products( - filter:$filterInput -){ - items{ - id - name - sku - } -} - + $query = <<<QUERY +query GetProducts(\$filterInput:ProductFilterInput){ + products( + filter:\$filterInput + ){ + items{ + id + name + sku + } + } } QUERY; $variables = [ @@ -211,17 +210,17 @@ public function testDispatchGetWithParameterizedVariables() : void 'sku' =>['eq' => 'simple1'] ] ]; - $postData = [ - 'query' => $query1, + $queryParams = [ + 'query' => $query, 'variables' => json_encode($variables), - 'operationName' => null + 'operationName' => 'GetProducts' ]; /** @var Http $request */ $request = $this->objectManager->get(Http::class); $request->setPathInfo('/graphql'); $request->setMethod('GET'); - $request->setParams($postData); + $request->setParams($queryParams); $response = $this->graphql->dispatch($request); $output = $this->jsonSerializer->unserialize($response->getContent()); $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); From cab46a10c79c62caa9f9109918dc311a200884cd Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 29 Mar 2019 11:47:32 -0500 Subject: [PATCH 271/603] 229: [GraphQL caching] Add support for queries via HTTP GET --- .../Exception/GraphQlRequestException.php | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 lib/internal/Magento/Framework/GraphQl/Exception/GraphQlRequestException.php diff --git a/lib/internal/Magento/Framework/GraphQl/Exception/GraphQlRequestException.php b/lib/internal/Magento/Framework/GraphQl/Exception/GraphQlRequestException.php new file mode 100644 index 0000000000000..8fef0a4791081 --- /dev/null +++ b/lib/internal/Magento/Framework/GraphQl/Exception/GraphQlRequestException.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Framework\GraphQl\Exception; + +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Phrase; + +/** + * Exception for GraphQL to be thrown when user supplies invalid input + */ +class GraphQlRequestException extends LocalizedException implements \GraphQL\Error\ClientAware +{ + const EXCEPTION_CATEGORY = 'graphql-request'; + + /** + * @var boolean + */ + private $isSafe; + + /** + * Initialize object + * + * @param Phrase $phrase + * @param \Exception $cause + * @param int $code + * @param boolean $isSafe + */ + public function __construct(Phrase $phrase, \Exception $cause = null, $code = 0, $isSafe = true) + { + $this->isSafe = $isSafe; + parent::__construct($phrase, $cause, $code); + } + + /** + * @inheritdoc + */ + public function isClientSafe() : bool + { + return $this->isSafe; + } + + /** + * @inheritdoc + */ + public function getCategory() : string + { + return self::EXCEPTION_CATEGORY; + } +} From 1f5e89b346677922eeb6fd11a7efd2456be4f226 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Fri, 29 Mar 2019 19:47:54 +0200 Subject: [PATCH 272/603] MAGETWO-70996: [GitHub] Customer Address "default billing address" Attribute Not Used in Checkout #8777 --- .../Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml index 7f9ba744507bb..cbe71e9cffa60 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml @@ -54,7 +54,6 @@ <element name="addressBook" type="button" selector="//a[text()='Address Book']"/> <element name="noQuotes" type="text" selector=".no-quotes-block"/> <element name="paymentMethodByName" type="text" selector="//*[@id='checkout-payment-method-load']//*[contains(@class, 'payment-group')]//label[normalize-space(.)='{{var1}}']" parameterized="true"/> - <element name="billingAddressSelect" type="select" selector=".payment-method._active select[name='billing_address_id']"/> <element name="billingAddressSelectShared" type="select" selector=".checkout-billing-address select[name='billing_address_id']"/> </section> </sections> From df001b8c171055f2d4ced89f93ca7306c98e5a11 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Fri, 29 Mar 2019 15:58:25 -0500 Subject: [PATCH 273/603] MC-13709: Create configurable product with out of stock child product, display out of stock products = yes - This test fails when extensions are enabled. I'm pulling it out of this weeks pr for now. --- ...eProductWithOutOfStockChildProductTest.xml | 123 ------------------ 1 file changed, 123 deletions(-) delete mode 100644 app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithOutOfStockChildProductTest.xml diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithOutOfStockChildProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithOutOfStockChildProductTest.xml deleted file mode 100644 index 9331b1f18fc5c..0000000000000 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithOutOfStockChildProductTest.xml +++ /dev/null @@ -1,123 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="AdminCreateConfigurableProductWithOutOfStockChildProductTest"> - <annotations> - <features value="ConfigurableProduct"/> - <stories value="Create configurable product"/> - <title value="Create configurable product with out of stock child product, display out of stock products = yes"/> - <description value="Admin should be able to create configurable product with one new out of stock child product, assigned to category"/> - <testCaseId value="MC-13709"/> - <severity value="CRITICAL"/> - <group value="mtf_migrated"/> - </annotations> - <before> - <!-- Create attribute with one options --> - <createData entity="productAttributeWithTwoOptionsNotVisible" stepKey="createConfigProductAttribute"/> - <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </createData> - <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </createData> - <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </getData> - - <!-- Create the child that will be a part of the configurable product --> - <createData entity="ApiSimpleOutOfStock" stepKey="createSimpleProduct"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - <requiredEntity createDataKey="getConfigAttributeOption"/> - </createData> - <createData entity="SimpleSubCategory" stepKey="createCategory"/> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - </before> - <after> - <!-- Don't display out of stock product --> - <actionGroup ref="noDisplayOutOfStockProduct" stepKey="revertDisplayOutOfStockProduct"/> - - <!-- Delete configurable product --> - <actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteProduct"> - <argument name="product" value="ApiConfigurableProduct"/> - </actionGroup> - - <!-- Delete created data --> - <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> - <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - - <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> - </after> - - <!-- Create configurable product --> - <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> - <waitForPageLoad stepKey="waitForProductGridPageLoad"/> - <actionGroup ref="goToCreateProductPage" stepKey="createConfigurableProduct"> - <argument name="product" value="ApiConfigurableProduct"/> - </actionGroup> - - <!-- Fill configurable product values --> - <actionGroup ref="fillMainProductForm" stepKey="fillConfigurableProductValues"> - <argument name="product" value="ApiConfigurableProduct"/> - </actionGroup> - - <!-- Create product configurations and add attribute and select all options --> - <actionGroup ref="generateConfigurationsByAttributeCode" stepKey="generateConfigurationsByAttributeCode" after="fillConfigurableProductValues"> - <argument name="attributeCode" value="$$createConfigProductAttribute.attribute_code$$"/> - </actionGroup> - - <!-- Add configurable product to category --> - <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory" after="fillConfigurableProductValues"/> - - <!-- Add child product to configurations grid --> - <actionGroup ref="addProductToConfigurationsGrid" stepKey="addSimpleProduct"> - <argument name="sku" value="$$createSimpleProduct.sku$$"/> - <argument name="name" value="$$createConfigProductAttributeOption.option[store_labels][1][label]$$"/> - </actionGroup> - - <!-- Save configurable product --> - <actionGroup ref="saveProductForm" stepKey="saveConfigurableProduct"/> - - <!-- Find configurable product in grid --> - <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="visitAdminProductPage"/> - <waitForPageLoad stepKey="waitForAdminProductPageLoad"/> - <actionGroup ref="filterProductGridBySku" stepKey="findCreatedConfigurableProduct"> - <argument name="product" value="ApiConfigurableProduct"/> - </actionGroup> - - <!-- Assert configurable product on admin product page --> - <click selector="{{AdminProductGridSection.firstRow}}" stepKey="clickOnProductPage"/> - <waitForPageLoad stepKey="waitForProductPageLoad"/> - <actionGroup ref="assertConfigurableProductOnAdminProductPage" stepKey="assertConfigurableProductOnAdminProductPage"> - <argument name="product" value="ApiConfigurableProduct"/> - </actionGroup> - - <!-- Assert configurable attributes block is present on product page --> - <seeElement selector="{{AdminProductFormConfigurationsSection.createdConfigurationsBlock}}" stepKey="seeCreatedConfigurations"/> - - <!-- Display out of stock product --> - <actionGroup ref="displayOutOfStockProduct" stepKey="displayOutOfStockProduct"/> - - <!-- Flash cache --> - <magentoCLI command="cache:flush" stepKey="flushCache"/> - - <!--Assert configurable product in category --> - <amOnPage url="$$createCategory.name$$.html" stepKey="amOnCategoryPage"/> - <waitForPageLoad stepKey="waitForCategoryPageLoad"/> - <actionGroup ref="StorefrontCheckCategoryOutOfStockConfigurableProduct" stepKey="assertConfigurableProductInCategory"> - <argument name="product" value="ApiConfigurableProduct"/> - </actionGroup> - - <!-- Assert configurable product is out of stock--> - <amOnPage url="{{ApiConfigurableProduct.urlKey}}.html" stepKey="amOnProductPage"/> - <waitForPageLoad stepKey="waitForPageLoad"/> - <see stepKey="checkForOutOfStock" selector="{{StorefrontProductInfoMainSection.stockIndication}}" userInput="OUT OF STOCK"/> - </test> -</tests> From b49305c10a4f7870f1c1a882bc20838a189d47a4 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Sat, 30 Mar 2019 00:08:51 +0200 Subject: [PATCH 274/603] Add arguments to AdminNewUserInvalidCurrentUserPasswordActionGroup, add review suggestions --- ...rInvalidCurrentUserPasswordActionGroup.xml | 26 +++++--- .../Security/Test/Mftf/Data/AdminUserData.xml | 2 +- .../LockAdminUserWhenCreatingNewUserTest.xml | 62 ++++++++++++++++--- .../LockAdminUserWhenCreatingNewUserTest.xml | 1 + 4 files changed, 75 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml b/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml index 4721106c1e317..0992dd23c76f4 100644 --- a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml +++ b/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml @@ -8,17 +8,27 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminNewUserInvalidCurrentUserPasswordActionGroup"> + <arguments> + <argument name="adminUser" type="string" /> + <argument name="adminFirstname" type="string" /> + <argument name="adminLastname" type="string" /> + <argument name="adminEmail" type="string" /> + <argument name="adminPassword" type="string" /> + <argument name="adminPasswordConfirmation" type="string" /> + <argument name="currentAdminPassword" type="string" /> + <argument name="adminUserRole" type="string"/> + </arguments> <!-- Fill in all data according to data set (current password is incorrect). --> - <fillField selector="{{AdminNewUserSection.username}}" userInput="{{AdminUserData.username}}" stepKey="fillUser"/> - <fillField selector="{{AdminNewUserSection.firstname}}" userInput="{{AdminUserData.firstname}}" stepKey="fillFirstName"/> - <fillField selector="{{AdminNewUserSection.lastname}}" userInput="{{AdminUserData.lastname}}" stepKey="fillLastName"/> - <fillField selector="{{AdminNewUserSection.email}}" userInput="{{AdminUserData.email}}" stepKey="fillEmail"/> - <fillField selector="{{AdminNewUserSection.password}}" userInput="{{AdminUserData.password}}" stepKey="fillPassword"/> - <fillField selector="{{AdminNewUserSection.confirmation}}" userInput="{{AdminUserData.password}}" stepKey="fillPasswordConfirmation"/> - <fillField selector="{{AdminNewUserSection.currentPassword}}" userInput="{{AdminUserData.password}}INVALID" stepKey="fillCurrentUserPassword"/> + <fillField selector="{{AdminNewUserSection.username}}" userInput="{{adminUser}}" stepKey="fillUser"/> + <fillField selector="{{AdminNewUserSection.firstname}}" userInput="{{adminFirstname}}" stepKey="fillFirstName"/> + <fillField selector="{{AdminNewUserSection.lastname}}" userInput="{{adminLastname}}" stepKey="fillLastName"/> + <fillField selector="{{AdminNewUserSection.email}}" userInput="{{adminEmail}}" stepKey="fillEmail"/> + <fillField selector="{{AdminNewUserSection.password}}" userInput="{{adminPassword}}" stepKey="fillPassword"/> + <fillField selector="{{AdminNewUserSection.confirmation}}" userInput="{{adminPasswordConfirmation}}" stepKey="fillPasswordConfirmation"/> + <fillField selector="{{AdminNewUserSection.currentPassword}}" userInput="{{currentAdminPassword}}" stepKey="fillCurrentUserPassword"/> <scrollToTopOfPage stepKey="ScrollToTopOfPage"/> <click selector="{{AdminNewUserSection.userRoleTab}}" stepKey="openUserRoleTab"/> - <click selector="{{AdminNewUserSection.administratorRole('1')}}" stepKey="assignRole"/> + <click selector="{{adminUserRole}}" stepKey="assignRole"/> <click selector="{{AdminNewUserSection.save}}" stepKey="saveNewUser"/> <waitForPageLoad stepKey="waitForSaveResultLoad"/> </actionGroup> diff --git a/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml b/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml index 65b18910098ad..1b3ec0ab351b9 100644 --- a/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml +++ b/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml @@ -11,7 +11,7 @@ <entity name="AdminUserData" type="admin"> <data key="email" unique="prefix">John.Doe@example.com</data> <data key="firstname">John</data> - <data key="username">lockuser</data> + <data key="username" unique="prefix">lockuser</data> <data key="lastname">Doe</data> <data key="password">pwdTest123!</data> </entity> diff --git a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml index 1aa0fdfc8b8fc..ec4dcd8dd0f6d 100644 --- a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml +++ b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml @@ -33,20 +33,68 @@ <!-- Perform add new admin user 6 specified number of times. "The password entered for the current user is invalid. Verify the password and try again." appears after each attempt.--> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt1"> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserFirstAttempt"> + <argument name="adminUser" value="{{AdminUserData.username}}" /> + <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> + <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> + <argument name="adminEmail" value="{{AdminUserData.email}}" /> + <argument name="adminPassword" value="{{AdminUserData.password}}" /> + <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> + <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> + <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> </actionGroup> <waitForPageLoad stepKey="waitForSaveResultLoad"/> <see selector="{{AdminMessagesSection.error}}" userInput="The password entered for the current user is invalid. Verify the password and try again." stepKey="seeInvalidPasswordError"/> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt2"> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserSecondAttempt"> + <argument name="adminUser" value="{{AdminUserData.username}}" /> + <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> + <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> + <argument name="adminEmail" value="{{AdminUserData.email}}" /> + <argument name="adminPassword" value="{{AdminUserData.password}}" /> + <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> + <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> + <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt3"> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserThirdAttempt"> + <argument name="adminUser" value="{{AdminUserData.username}}" /> + <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> + <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> + <argument name="adminEmail" value="{{AdminUserData.email}}" /> + <argument name="adminPassword" value="{{AdminUserData.password}}" /> + <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> + <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> + <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt4"> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserFourthAttempt"> + <argument name="adminUser" value="{{AdminUserData.username}}" /> + <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> + <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> + <argument name="adminEmail" value="{{AdminUserData.email}}" /> + <argument name="adminPassword" value="{{AdminUserData.password}}" /> + <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> + <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> + <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt5"> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserFifthAttempt"> + <argument name="adminUser" value="{{AdminUserData.username}}" /> + <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> + <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> + <argument name="adminEmail" value="{{AdminUserData.email}}" /> + <argument name="adminPassword" value="{{AdminUserData.password}}" /> + <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> + <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> + <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserAttempt6"> + <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserSixthAttempt"> + <argument name="adminUser" value="{{AdminUserData.username}}" /> + <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> + <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> + <argument name="adminEmail" value="{{AdminUserData.email}}" /> + <argument name="adminPassword" value="{{AdminUserData.password}}" /> + <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> + <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> + <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> </actionGroup> <!-- Check Error that account has been locked --> @@ -57,6 +105,6 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> <waitForPageLoad stepKey="waitForError"/> <see selector="{{AdminLoginFormSection.error}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later" - stepKey="seeLockUserError2"/> + stepKey="seeLoginUserError"/> </test> </tests> diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.xml index c4cfe3f7f274c..4d0c58fb1e07b 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.xml @@ -19,6 +19,7 @@ <data name="user/data/password_confirmation" xsi:type="string">123123q</data> <data name="user/data/current_password" xsi:type="string">incorrect password</data> <data name="attempts" xsi:type="string">4</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Security\Test\Constraint\AssertUserIsLocked" /> </variation> </testCase> From bd2e5c10d04e37e823c0c3a4917baa6939ff4f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= <lukasz.bajsarowicz@gmail.com> Date: Fri, 29 Mar 2019 23:01:47 +0000 Subject: [PATCH 275/603] PR#21647 Remove another redundant file --- .../Test/Mftf/MetaData/url_rewrite-meta.xml | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 app/code/Magento/UrlRewrite/Test/Mftf/MetaData/url_rewrite-meta.xml diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/MetaData/url_rewrite-meta.xml b/app/code/Magento/UrlRewrite/Test/Mftf/MetaData/url_rewrite-meta.xml deleted file mode 100644 index 0738b17d6e0f0..0000000000000 --- a/app/code/Magento/UrlRewrite/Test/Mftf/MetaData/url_rewrite-meta.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?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="CreateUrlRewrite" dataType="urlRewrite" type="create" auth="adminFormKey" url="/admin/url_rewrite/save/" method="POST" successRegex="/messages-message-success/"> - <field key="store_id">integer</field> - <field key="redirect_type">integer</field> - <field key="request_path">string</field> - <field key="target_path">string</field> - <field key="description">string</field> - </operation> -</operations> From e21b9dc0433cb3c22df8f573a1c8fbe088a5e76c Mon Sep 17 00:00:00 2001 From: "Iskander (Alex) Sharipov" <quasilyte@gmail.com> Date: Sat, 30 Mar 2019 03:48:39 +0300 Subject: [PATCH 276/603] fix strpos args order --- .../testsuite/Magento/Analytics/Api/LinkProviderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Analytics/Api/LinkProviderTest.php b/dev/tests/api-functional/testsuite/Magento/Analytics/Api/LinkProviderTest.php index 6fd7551676660..4bf1335f20667 100644 --- a/dev/tests/api-functional/testsuite/Magento/Analytics/Api/LinkProviderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Analytics/Api/LinkProviderTest.php @@ -95,6 +95,6 @@ public function testGetAll() */ private function isTestBaseUrlSecure() { - return strpos('https://', TESTS_BASE_URL) !== false; + return strpos(TESTS_BASE_URL, 'https://') !== false; } } From 8d671b20484a35b87224c58031a94dfc5cdc2355 Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Sat, 30 Mar 2019 10:23:21 +0530 Subject: [PATCH 277/603] Correct spelling --- app/code/Magento/Bundle/Block/Checkout/Cart/Item/Renderer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Bundle/Block/Checkout/Cart/Item/Renderer.php b/app/code/Magento/Bundle/Block/Checkout/Cart/Item/Renderer.php index c75ebc700603b..b117c127dff39 100644 --- a/app/code/Magento/Bundle/Block/Checkout/Cart/Item/Renderer.php +++ b/app/code/Magento/Bundle/Block/Checkout/Cart/Item/Renderer.php @@ -88,7 +88,7 @@ public function getMessages() $messages = []; $quoteItem = $this->getItem(); - // Add basic messages occuring during this page load + // Add basic messages occurring during this page load $baseMessages = $quoteItem->getMessage(false); if ($baseMessages) { foreach ($baseMessages as $message) { From cb015a1dd94ed73623c620fd535e02131d3efb4c Mon Sep 17 00:00:00 2001 From: Ansari <ziyaurrahman@krishtechnolabs.com> Date: Sat, 30 Mar 2019 11:02:05 +0530 Subject: [PATCH 278/603] Spelling Correction --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b86c7b79a0cbd..323116560a7cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -785,7 +785,7 @@ Tests: * Refactored controller actions in the Product area * Moved commands cache.php, indexer.php, log.php, test.php, compiler.php, singletenant\_compiler.php, generator.php, pack.php, deploy.php and file\_assembler.php to the new bin/magento CLI framework * Data Migration Tool - * The Data Migraiton Tool is published in the separate [repository](https://github.com/magento/data-migration-tool-ce "Data Migration Tool repository") + * The Data Migration Tool is published in the separate [repository](https://github.com/magento/data-migration-tool-ce "Data Migration Tool repository") * Fixed bugs * Fixed an issue where error appeared during placing order with virtual product * Fixed an issue where billing and shipping sections didn't contain address information on order print From 2038d7d00ae6428fd4aea976f275ff01924eecee Mon Sep 17 00:00:00 2001 From: Sergey Nezbritskiy <sergeyn@corra.com> Date: Thu, 28 Mar 2019 10:23:27 +0200 Subject: [PATCH 279/603] Flush totalRecords when clearing data collection --- .../Entity/Collection/AbstractCollection.php | 13 +----------- .../Adminhtml/Edit/Tab/View/CartTest.php | 11 ---------- .../Magento/Framework/Data/Collection.php | 1 + .../Test/Unit/Data/CollectionTest.php | 21 +++++++++++++++++++ 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index dad420ea0b375..247ee2d5423cd 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -395,7 +395,7 @@ public function addAttributeToFilter($attribute, $condition = null, $joinType = if (!empty($conditionSql)) { $this->getSelect()->where($conditionSql, null, \Magento\Framework\DB\Select::TYPE_CONDITION); - $this->invalidateSize(); + $this->_totalRecords = null; } else { throw new \Magento\Framework\Exception\LocalizedException( __('Invalid attribute identifier for filter (%1)', get_class($attribute)) @@ -1720,15 +1720,4 @@ public function removeAllFieldsFromSelect() return $this->removeAttributeToSelect(); } - /** - * Invalidates "Total Records Count". - * Invalidates saved "Total Records Count" attribute with last counting, - * so a next calling of method getSize() will query new total records count. - * - * @return void - */ - private function invalidateSize(): void - { - $this->_totalRecords = null; - } } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php index 3bb10baff6572..396d3b60e4f20 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php @@ -100,15 +100,4 @@ public function testToHtmlCartItem() $this->assertContains('$10.00', $html); $this->assertContains('catalog/product/edit/id/1', $html); } - - /** - * Verify that the customer has a single item in his cart. - * - * @magentoDataFixture Magento/Customer/_files/customer.php - * @magentoDataFixture Magento/Customer/_files/quote.php - */ - public function testGetCollection() - { - $this->assertEquals(1, $this->block->getCollection()->getSize()); - } } diff --git a/lib/internal/Magento/Framework/Data/Collection.php b/lib/internal/Magento/Framework/Data/Collection.php index dbafc9734e091..82f0ee1da464a 100644 --- a/lib/internal/Magento/Framework/Data/Collection.php +++ b/lib/internal/Magento/Framework/Data/Collection.php @@ -492,6 +492,7 @@ public function clear() { $this->_setIsLoaded(false); $this->_items = []; + $this->_totalRecords = null; return $this; } diff --git a/lib/internal/Magento/Framework/Test/Unit/Data/CollectionTest.php b/lib/internal/Magento/Framework/Test/Unit/Data/CollectionTest.php index 75f8b1cd0633f..913d5a577e62a 100644 --- a/lib/internal/Magento/Framework/Test/Unit/Data/CollectionTest.php +++ b/lib/internal/Magento/Framework/Test/Unit/Data/CollectionTest.php @@ -57,6 +57,27 @@ public function testWalk() ); } + /** + * Ensure that getSize works correctly with clear + * + */ + public function testClearTotalRecords() + { + $objOne = new \Magento\Framework\DataObject(['id' => 1, 'name' => 'one']); + $objTwo = new \Magento\Framework\DataObject(['id' => 2, 'name' => 'two']); + $objThree = new \Magento\Framework\DataObject(['id' => 3, 'name' => 'three']); + + /** @noinspection PhpUnhandledExceptionInspection */ + $this->collection->addItem($objOne); + /** @noinspection PhpUnhandledExceptionInspection */ + $this->collection->addItem($objTwo); + /** @noinspection PhpUnhandledExceptionInspection */ + $this->collection->addItem($objThree); + $this->assertEquals(3, $this->collection->getSize()); + $this->collection->clear(); + $this->assertEquals(0, $this->collection->getSize()); + } + /** * Callback function. * From 6076fdcd20ebc1b6e9e1f10b5c99ea4e28f46365 Mon Sep 17 00:00:00 2001 From: Jeff Coleman <jeff@jeffcolemanwrites.com> Date: Sun, 31 Mar 2019 07:10:58 -0700 Subject: [PATCH 280/603] Setting initial downloadable item status to available if \Magento\Downloadable\Model\Link\Purchased\Item::XML_PATH_ORDER_ITEM_STATUS is set to 'Pending' (https://github.com/magento/magento2/issues/21753) --- .../Observer/SaveDownloadableOrderItemObserver.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php index 64305cfce9b08..ef763336a6515 100644 --- a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php +++ b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php @@ -92,6 +92,11 @@ public function execute(\Magento\Framework\Event\Observer $observer) if ($purchasedLink->getId()) { return $this; } + $orderItemStatusToEnable = $this->_scopeConfig->getValue( + \Magento\Downloadable\Model\Link\Purchased\Item::XML_PATH_ORDER_ITEM_STATUS, + ScopeInterface::SCOPE_STORE, + $orderItem->getOrder()->getStoreId() + ); if (!$product) { $product = $this->_createProductModel()->setStoreId( $orderItem->getOrder()->getStoreId() @@ -150,6 +155,8 @@ public function execute(\Magento\Framework\Event\Observer $observer) )->setNumberOfDownloadsBought( $numberOfDownloads )->setStatus( + 1 == $orderItemStatusToEnable ? + \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_AVAILABLE : \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_PENDING )->setCreatedAt( $orderItem->getCreatedAt() From d32da36e6cbddc176524ac4b68dc6fb78e1eda90 Mon Sep 17 00:00:00 2001 From: Jeff Coleman <jeff@jeffcolemanwrites.com> Date: Sun, 31 Mar 2019 08:17:45 -0700 Subject: [PATCH 281/603] fix for coding style --- .../Observer/SaveDownloadableOrderItemObserver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php index ef763336a6515..f2a1e981c2357 100644 --- a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php +++ b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php @@ -92,7 +92,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) if ($purchasedLink->getId()) { return $this; } - $orderItemStatusToEnable = $this->_scopeConfig->getValue( + $statusToEnable = $this->_scopeConfig->getValue( \Magento\Downloadable\Model\Link\Purchased\Item::XML_PATH_ORDER_ITEM_STATUS, ScopeInterface::SCOPE_STORE, $orderItem->getOrder()->getStoreId() @@ -155,7 +155,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) )->setNumberOfDownloadsBought( $numberOfDownloads )->setStatus( - 1 == $orderItemStatusToEnable ? + 1 == $statusToEnable ? \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_AVAILABLE : \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_PENDING )->setCreatedAt( From 4ccc97937682e20c7d58a517563ca8e58f4ec7bc Mon Sep 17 00:00:00 2001 From: Valerij Ivashchenko <likemusicdev@gmail.com> Date: Sun, 31 Mar 2019 18:42:40 +0300 Subject: [PATCH 282/603] Add space after asterisk to show as list On https://devdocs.magento.com/guides/v2.3/mrg/ce/Paypal.html --- app/code/Magento/Paypal/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Paypal/README.md b/app/code/Magento/Paypal/README.md index 8f4453ae0a058..0ed4f2e90291b 100644 --- a/app/code/Magento/Paypal/README.md +++ b/app/code/Magento/Paypal/README.md @@ -1,6 +1,6 @@ Module Magento\PayPal implements integration with the PayPal payment system. Namely, it enables the following payment methods: -*PayPal Express Checkout -*PayPal Payments Standard -*PayPal Payments Pro -*PayPal Credit -*PayFlow Payment Gateway +* PayPal Express Checkout +* PayPal Payments Standard +* PayPal Payments Pro +* PayPal Credit +* PayFlow Payment Gateway From 2c166978e48e502ca86c267e07acc075a1720ec7 Mon Sep 17 00:00:00 2001 From: Jeff Coleman <jeff@jeffcolemanwrites.com> Date: Sun, 31 Mar 2019 15:27:25 -0700 Subject: [PATCH 283/603] renamed variable for clarity and used defined constant for comparison --- .../Observer/SaveDownloadableOrderItemObserver.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php index f2a1e981c2357..fb4af4c3443a9 100644 --- a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php +++ b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php @@ -92,7 +92,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) if ($purchasedLink->getId()) { return $this; } - $statusToEnable = $this->_scopeConfig->getValue( + $orderStatusToEnableItem = $this->_scopeConfig->getValue( \Magento\Downloadable\Model\Link\Purchased\Item::XML_PATH_ORDER_ITEM_STATUS, ScopeInterface::SCOPE_STORE, $orderItem->getOrder()->getStoreId() @@ -155,10 +155,10 @@ public function execute(\Magento\Framework\Event\Observer $observer) )->setNumberOfDownloadsBought( $numberOfDownloads )->setStatus( - 1 == $statusToEnable ? + \Magento\Sales\Model\Order\Item::STATUS_PENDING == $orderStatusToEnableItem ? \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_AVAILABLE : \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_PENDING - )->setCreatedAt( + )->setCreatedAt( $orderItem->getCreatedAt() )->setUpdatedAt( $orderItem->getUpdatedAt() From d53690cbfe4aeac02d05c2078424698ce1fb7d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20K=C3=B6cke?= <jens@koecke.net> Date: Mon, 1 Apr 2019 07:21:11 +0200 Subject: [PATCH 284/603] Fix unit tests --- .../Unit/Console/Command/ConfigSet/DefaultProcessorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/DefaultProcessorTest.php b/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/DefaultProcessorTest.php index edb76c067bf35..35b2406b328cb 100644 --- a/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/DefaultProcessorTest.php +++ b/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/DefaultProcessorTest.php @@ -103,7 +103,7 @@ public function testProcess($path, $value, $scope, $scopeCode) $config = $this->createMock(Config::class); $this->configFactory->expects($this->once()) ->method('create') - ->with(['scope' => $scope, 'scope_code' => $scopeCode]) + ->with(['data' => ['scope' => $scope, 'scope_code' => $scopeCode]]) ->willReturn($config); $config->expects($this->once()) ->method('setDataByPath') From 81cb7bd14c5843800063564821887cd3f248b704 Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin <serhiy.yelahin@transoftgroup.com> Date: Mon, 1 Apr 2019 09:32:03 +0300 Subject: [PATCH 285/603] MAGETWO-98886: Gift Card Accounts: expiration date subtracts one day --- .../Magento/Framework/Data/Form/Element/DateTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/Data/Form/Element/DateTest.php b/dev/tests/integration/testsuite/Magento/Framework/Data/Form/Element/DateTest.php index a64df0451f9c0..9980f40239f8c 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Data/Form/Element/DateTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Data/Form/Element/DateTest.php @@ -17,7 +17,7 @@ class DateTest extends \PHPUnit\Framework\TestCase /** * @var ElementFactory */ - protected $_elementFactory; + private $elementFactory; /** * @inheritdoc @@ -25,7 +25,7 @@ class DateTest extends \PHPUnit\Framework\TestCase protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->_elementFactory = $objectManager->create(ElementFactory::class); + $this->elementFactory = $objectManager->create(ElementFactory::class); } /** @@ -39,7 +39,7 @@ protected function setUp() public function testGetValue(array $data, string $expect): void { /** @var $date Date */ - $date = $this->_elementFactory->create(Date::class, $data); + $date = $this->elementFactory->create(Date::class, $data); $this->assertEquals($expect, $date->getValue()); } From b5b162513843d837292af4111b9fdd5f44cb708d Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Mon, 1 Apr 2019 09:54:32 +0300 Subject: [PATCH 286/603] MAGETWO-97423: Price column in sales_order_item table shows the price including tax when Custom Price is applied on admin order --- .../Total/Quote/CommonTaxCollectorTest.php | 4 +- .../Tax/Model/Sales/Total/Quote/SetupUtil.php | 58 ++++++++++++++----- .../including_tax_with_custom_price.php | 2 +- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/CommonTaxCollectorTest.php b/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/CommonTaxCollectorTest.php index 711ead4625659..50d45ad662bd4 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/CommonTaxCollectorTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/CommonTaxCollectorTest.php @@ -83,7 +83,7 @@ class CommonTaxCollectorTest extends TestCase /** * @var TaxHelper */ - protected $taxHelper; + private $taxHelper; /** * {@inheritdoc} @@ -152,6 +152,8 @@ protected function setUp() * @param bool $useBaseCurrency * @param string $shippingTaxClass * @param bool $shippingPriceInclTax + * + * @return void * @dataProvider getShippingDataObjectDataProvider */ public function testGetShippingDataObject( diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php index 0ae021b4e9036..985019b687ce0 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php @@ -7,10 +7,15 @@ namespace Magento\Tax\Model\Sales\Total\Quote; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Quote\Model\Quote; use Magento\Tax\Model\Config; use Magento\Tax\Model\Calculation; use Magento\Quote\Model\Quote\Item\Updater; -use \Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Framework\Api\Filter; +use Magento\Framework\Api\Search\FilterGroup; +use Magento\Framework\Api\SearchCriteriaInterface; /** * Setup utility for quote @@ -598,7 +603,7 @@ protected function createCartRule($ruleDataOverride) * * @param array $quoteData * @param \Magento\Customer\Api\Data\CustomerInterface $customer - * @return \Magento\Quote\Model\Quote + * @return Quote */ protected function createQuote($quoteData, $customer) { @@ -623,8 +628,8 @@ protected function createQuote($quoteData, $customer) $quoteBillingAddress = $this->objectManager->create(\Magento\Quote\Model\Quote\Address::class); $quoteBillingAddress->importCustomerAddressData($addressService->getById($billingAddress->getId())); - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); $quote->setStoreId(1) ->setIsActive(true) ->setIsMultiShipping(false) @@ -638,7 +643,7 @@ protected function createQuote($quoteData, $customer) /** * Add products to quote * - * @param \Magento\Quote\Model\Quote $quote + * @param Quote $quote * @param array $itemsData * @return $this */ @@ -661,7 +666,8 @@ protected function addProductToQuote($quote, $itemsData) * Create a quote based on given data * * @param array $quoteData - * @return \Magento\Quote\Model\Quote + * + * @return Quote */ public function setupQuote($quoteData) { @@ -671,16 +677,7 @@ public function setupQuote($quoteData) $this->addProductToQuote($quote, $quoteData['items']); if (isset($quoteData['update_items'])) { - $updater = $this->objectManager->get(Updater::class); - $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); - foreach ($quoteData['update_items'] as $sku => $updateItem) { - $product = $productRepository->get($sku); - $quoteItem = $quote->getItemByProduct($product); - $updater->update( - $quoteItem, - $updateItem - ); - } + $this->updateItems($quote, $quoteData['update_items']); } //Set shipping amount if (isset($quoteData['shipping_method'])) { @@ -698,4 +695,33 @@ public function setupQuote($quoteData) return $quote; } + + /** + * Update quote items + * + * @param Quote $quote + * @param array $items + * + * @return void + */ + private function updateItems(Quote $quote, array $items): void + { + $updater = $this->objectManager->get(Updater::class); + $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $filter = $this->objectManager->create(Filter::class); + $filter->setField('sku')->setValue(array_keys($items)); + $filterGroup = $this->objectManager->create(FilterGroup::class); + $filterGroup->setFilters([$filter]); + $searchCriteria = $this->objectManager->create(SearchCriteriaInterface::class); + $searchCriteria->setFilterGroups([$filterGroup]); + $products = $productRepository->getList($searchCriteria)->getItems(); + /** @var ProductInterface $product */ + foreach ($products as $product) { + $quoteItem = $quote->getItemByProduct($product); + $updater->update( + $quoteItem, + $items[$product->getSku()] + ); + } + } } diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_with_custom_price.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_with_custom_price.php index 584b356beb53b..290c133f455f6 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_with_custom_price.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_with_custom_price.php @@ -12,7 +12,7 @@ 'config_data' => [ SetupUtil::CONFIG_OVERRIDES => [ Config::CONFIG_XML_PATH_PRICE_INCLUDES_TAX => 1, - Config::CONFIG_XML_PATH_APPLY_ON => 0 + Config::CONFIG_XML_PATH_APPLY_ON => 0, ], SetupUtil::TAX_RATE_OVERRIDES => [ SetupUtil::TAX_RATE_TX => 8.25, From 223d8efc62bed0ec5b42e027bb94bacfa38087c4 Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Mon, 1 Apr 2019 11:51:09 +0300 Subject: [PATCH 287/603] fix-issue-20186 --- .../Magento/Sniffs/Annotation/AnnotationFormatValidator.php | 4 ++-- .../Sniffs/Annotation/ClassAnnotationStructureSniff.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php b/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php index 49acd039a0960..3f477f7ce5033 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php +++ b/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php @@ -301,8 +301,8 @@ public function validateDescriptionFormatStructure( $this->validateShortDescriptionFormat( $phpcsFile, (int) $shortPtr, - $commentStartPtr, - $commentEndPtr, + (int)$commentStartPtr, + (int)$commentEndPtr, $emptyTypeTokens ); } diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotation/ClassAnnotationStructureSniff.php b/dev/tests/static/framework/Magento/Sniffs/Annotation/ClassAnnotationStructureSniff.php index 01834ff81e81b..c37f0b500fe39 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Annotation/ClassAnnotationStructureSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Annotation/ClassAnnotationStructureSniff.php @@ -97,8 +97,8 @@ public function process(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $previousCommentClosePtr = $phpcsFile->findPrevious(T_DOC_COMMENT_CLOSE_TAG, $stackPtr - 1, 0); - $this->validateAnnotationBlockExists($phpcsFile, $previousCommentClosePtr, $stackPtr); - $commentStartPtr = $phpcsFile->findPrevious(T_DOC_COMMENT_OPEN_TAG, $stackPtr - 1, 0); + $this->validateAnnotationBlockExists($phpcsFile, (int)$previousCommentClosePtr, (int)$stackPtr); + $commentStartPtr = (int)$phpcsFile->findPrevious(T_DOC_COMMENT_OPEN_TAG, $stackPtr - 1, 0); $commentCloserPtr = $tokens[$commentStartPtr]['comment_closer']; $emptyTypeTokens = [ T_DOC_COMMENT_WHITESPACE, @@ -111,7 +111,7 @@ public function process(File $phpcsFile, $stackPtr) } else { $this->annotationFormatValidator->validateDescriptionFormatStructure( $phpcsFile, - $commentStartPtr, + (int)$commentStartPtr, (int) $shortPtr, $previousCommentClosePtr, $emptyTypeTokens From f2faf154dddbcf5217dcc35fdac13f410ed8fe0d Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Mon, 1 Apr 2019 12:05:50 +0300 Subject: [PATCH 288/603] MAGETWO-97423: Price column in sales_order_item table shows the price including tax when Custom Price is applied on admin order --- .../Tax/Model/Sales/Total/Quote/CommonTaxCollector.php | 4 ++-- .../Magento/Tax/_files/tax_calculation_data_aggregated.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php index 31d5deb7ea0d5..77b3cfa3a08bb 100644 --- a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php +++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php @@ -348,7 +348,7 @@ public function mapItems( $useBaseCurrency ) { $items = $shippingAssignment->getItems(); - if (!count($items)) { + if (empty($items)) { return []; } @@ -478,7 +478,7 @@ protected function prepareQuoteDetails(ShippingAssignmentInterface $shippingAssi { $items = $shippingAssignment->getItems(); $address = $shippingAssignment->getShipping()->getAddress(); - if (!count($items)) { + if (empty($items)) { return $this->quoteDetailsDataObjectFactory->create(); } diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php b/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php index cdc3b7d135d1d..3c56b1bf815a6 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php @@ -6,12 +6,12 @@ declare(strict_types=1); /** - * Global array that holds test scenarios data + * Global array that holds test scenarios data. * * @var array */ $taxCalculationData = []; - +//phpcs:disable Magento2.Security.IncludeFile require_once __DIR__ . '/scenarios/excluding_tax_apply_tax_after_discount.php'; require_once __DIR__ . '/scenarios/excluding_tax_apply_tax_after_discount_discount_tax.php'; require_once __DIR__ . '/scenarios/excluding_tax_apply_tax_before_discount.php'; From 660f1fc4cf068bd10873197b1cec57f673931484 Mon Sep 17 00:00:00 2001 From: serhii balko <serhii.balko@transoftgroup.com> Date: Mon, 1 Apr 2019 12:33:53 +0300 Subject: [PATCH 289/603] MAGETWO-98603: [2.3] Fixed Tier Pricing for Bundle items doesn't work --- ...AdminCreateApiBundleProductActionGroup.xml | 58 ++++++++++ ...rontCheckBundleProductOptionTierPrices.xml | 102 +++++------------- .../DataProviders/OptionPriceRendererTest.php | 39 +++++-- .../product_with_simple_tier_pricing.php | 23 ++-- 4 files changed, 128 insertions(+), 94 deletions(-) diff --git a/app/code/Magento/Bundle/Test/Mftf/ActionGroup/AdminCreateApiBundleProductActionGroup.xml b/app/code/Magento/Bundle/Test/Mftf/ActionGroup/AdminCreateApiBundleProductActionGroup.xml index ad9a8253e910c..4cd16320d3d78 100644 --- a/app/code/Magento/Bundle/Test/Mftf/ActionGroup/AdminCreateApiBundleProductActionGroup.xml +++ b/app/code/Magento/Bundle/Test/Mftf/ActionGroup/AdminCreateApiBundleProductActionGroup.xml @@ -106,4 +106,62 @@ <requiredEntity createDataKey="simpleProduct4"/> </createData> </actionGroup> + <actionGroup name="AdminCreateApiDynamicBundleProductAllOptionTypesActionGroup"> + <arguments> + <argument name="productName" defaultValue="Api Dynamic Bundle Product" type="string"/> + </arguments> + <!-- Create simple products --> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"> + <field key="price">10</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"> + <field key="price">20</field> + </createData> + <!-- Create Bundle product --> + <createData entity="ApiBundleProduct" stepKey="createBundleProduct"> + <field key="name">{{productName}}</field> + </createData> + <createData entity="DropDownBundleOption" stepKey="createDropDownBundleOption"> + <requiredEntity createDataKey="createBundleProduct"/> + <field key="title">Drop-down Option</field> + </createData> + <createData entity="RadioButtonsOption" stepKey="createBundleRadioButtonsOption"> + <requiredEntity createDataKey="createBundleProduct"/> + <field key="title">Radio Buttons Option</field> + </createData> + <createData entity="CheckboxOption" stepKey="createBundleCheckboxOption"> + <requiredEntity createDataKey="createBundleProduct"/> + <field key="title">Checkbox Option</field> + </createData> + <createData entity="ApiBundleLink" stepKey="linkCheckboxOptionToProduct1"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleCheckboxOption"/> + <requiredEntity createDataKey="simpleProduct1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkCheckboxOptionToProduct2"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleCheckboxOption"/> + <requiredEntity createDataKey="simpleProduct2"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkDropDownOptionToProduct1"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createDropDownBundleOption"/> + <requiredEntity createDataKey="simpleProduct1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkDropDownOptionToProduct2"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createDropDownBundleOption"/> + <requiredEntity createDataKey="simpleProduct2"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkRadioButtonsOptionToProduct1"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleRadioButtonsOption"/> + <requiredEntity createDataKey="simpleProduct1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkRadioButtonsOptionToProduct2"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleRadioButtonsOption"/> + <requiredEntity createDataKey="simpleProduct2"/> + </createData> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml index 23d70c978ecd8..4c39cbc4ab0a4 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml @@ -14,137 +14,91 @@ <stories value="View bundle products"/> <title value="Check tier prices for bundle options"/> <testCaseId value="MAGETWO-98968"/> + <useCaseId value="MAGETWO-98603"/> + <group value="catalog"/> <group value="bundle"/> </annotations> <before> - <!-- Create simple products --> - <createData entity="SimpleProduct2" stepKey="simpleProduct1"> - <field key="price">10</field> - </createData> - <createData entity="SimpleProduct2" stepKey="simpleProduct2"> - <field key="price">20</field> - </createData> + <!-- Create Dynamic Bundle product --> + <actionGroup ref="AdminCreateApiDynamicBundleProductAllOptionTypesActionGroup" stepKey="createBundleProduct"/> <!-- Add tier prices to simple products --> + <!-- Simple product 1 --> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <amOnPage url="{{AdminProductEditPage.url($$simpleProduct1.id$$)}}" stepKey="openAdminEditPageProduct1"/> + <amOnPage url="{{AdminProductEditPage.url($$simpleProduct1CreateBundleProduct.id$$)}}" stepKey="openAdminEditPageProduct1"/> <actionGroup ref="ProductSetAdvancedPricing" stepKey="addTierPriceProduct1"> <argument name="group" value="ALL GROUPS"/> <argument name="quantity" value="5"/> <argument name="price" value="Discount"/> <argument name="amount" value="50"/> </actionGroup> - - <amOnPage url="{{AdminProductEditPage.url($$simpleProduct2.id$$)}}" stepKey="openAdminEditPageProduct2"/> + <!-- Simple product 2 --> + <amOnPage url="{{AdminProductEditPage.url($$simpleProduct2CreateBundleProduct.id$$)}}" stepKey="openAdminEditPageProduct2"/> <actionGroup ref="ProductSetAdvancedPricing" stepKey="addTierPriceProduct2"> <argument name="group" value="ALL GROUPS"/> <argument name="quantity" value="7"/> <argument name="price" value="Discount"/> <argument name="amount" value="25"/> </actionGroup> + <actionGroup ref="logout" stepKey="logoutAsAdmin"/> - <!-- Create Bundle product --> - <createData entity="ApiBundleProduct" stepKey="createBundleProduct"/> - <createData entity="DropDownBundleOption" stepKey="createDropDownBundleOption"> - <requiredEntity createDataKey="createBundleProduct"/> - <field key="title">Drop-down Option</field> - </createData> - <createData entity="RadioButtonsOption" stepKey="createBundleRadioButtonsOption"> - <requiredEntity createDataKey="createBundleProduct"/> - <field key="title">Radio Buttons Option</field> - </createData> - <createData entity="CheckboxOption" stepKey="createBundleCheckboxOption"> - <requiredEntity createDataKey="createBundleProduct"/> - <field key="title">Checkbox Option</field> - </createData> - <createData entity="ApiBundleLink" stepKey="linkCheckboxOptionToProduct1"> - <requiredEntity createDataKey="createBundleProduct"/> - <requiredEntity createDataKey="createBundleCheckboxOption"/> - <requiredEntity createDataKey="simpleProduct1"/> - </createData> - <createData entity="ApiBundleLink" stepKey="linkCheckboxOptionToProduct2"> - <requiredEntity createDataKey="createBundleProduct"/> - <requiredEntity createDataKey="createBundleCheckboxOption"/> - <requiredEntity createDataKey="simpleProduct2"/> - </createData> - <createData entity="ApiBundleLink" stepKey="linkDropDownOptionToProduct1"> - <requiredEntity createDataKey="createBundleProduct"/> - <requiredEntity createDataKey="createDropDownBundleOption"/> - <requiredEntity createDataKey="simpleProduct1"/> - </createData> - <createData entity="ApiBundleLink" stepKey="linkDropDownOptionToProduct2"> - <requiredEntity createDataKey="createBundleProduct"/> - <requiredEntity createDataKey="createDropDownBundleOption"/> - <requiredEntity createDataKey="simpleProduct2"/> - </createData> - <createData entity="ApiBundleLink" stepKey="linkRadioButtonsOptionToProduct1"> - <requiredEntity createDataKey="createBundleProduct"/> - <requiredEntity createDataKey="createBundleRadioButtonsOption"/> - <requiredEntity createDataKey="simpleProduct1"/> - </createData> - <createData entity="ApiBundleLink" stepKey="linkRadioButtonsOptionToProduct2"> - <requiredEntity createDataKey="createBundleProduct"/> - <requiredEntity createDataKey="createBundleRadioButtonsOption"/> - <requiredEntity createDataKey="simpleProduct2"/> - </createData> - + <!-- Run reindex --> <magentoCLI command="indexer:reindex" stepKey="reindex"/> </before> <after> - <deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/> - <deleteData createDataKey="simpleProduct2" stepKey="deleteSimpleProduct2"/> - <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> + <deleteData createDataKey="createBundleProductCreateBundleProduct" stepKey="deleteDynamicBundleProduct"/> + <deleteData createDataKey="simpleProduct1CreateBundleProduct" stepKey="deleteSimpleProduct1"/> + <deleteData createDataKey="simpleProduct2CreateBundleProduct" stepKey="deleteSimpleProduct2"/> </after> <!-- Go to storefront product page --> - <amOnPage url="{{StorefrontProductPage.url($$createBundleProduct.custom_attributes[url_key]$$)}}" stepKey="onPage"/> - <waitForPageLoad stepKey="waitForPageLoad"/> + <amOnPage url="{{StorefrontProductPage.url($$createBundleProductCreateBundleProduct.custom_attributes[url_key]$$)}}" stepKey="navigateToBundleProductPage"/> <click selector="{{StorefrontBundledSection.addToCart}}" stepKey="clickCustomize"/> <!--"Drop-down" type option--> <!-- Check Tier Prices for product 1 --> - <selectOption selector="{{StorefrontBundledSection.dropDownOptionOneProducts('Drop-down Option')}}" userInput="$$simpleProduct1.sku$$ +$$$simpleProduct1.price$$.00" stepKey="selectDropDownOptionProduct1"/> - <seeOptionIsSelected selector="{{StorefrontBundledSection.dropDownOptionOneProducts('Drop-down Option')}}" userInput="$$simpleProduct1.sku$$ +$$$simpleProduct1.price$$.00" stepKey="checkDropDownOptionProduct1"/> + <selectOption selector="{{StorefrontBundledSection.dropDownOptionOneProducts('Drop-down Option')}}" userInput="$$simpleProduct1CreateBundleProduct.sku$$ +$$$simpleProduct1CreateBundleProduct.price$$.00" stepKey="selectDropDownOptionProduct1"/> + <seeOptionIsSelected selector="{{StorefrontBundledSection.dropDownOptionOneProducts('Drop-down Option')}}" userInput="$$simpleProduct1CreateBundleProduct.sku$$ +$$$simpleProduct1CreateBundleProduct.price$$.00" stepKey="checkDropDownOptionProduct1"/> <grabTextFrom selector="{{StorefrontBundledSection.dropDownOptionTierPrices('Drop-down Option')}}" stepKey="DropDownTierPriceTextProduct1"/> <assertContains stepKey="assertDropDownTierPriceTextProduct1"> <expectedResult type="string">Buy 5 for $5.00 each and save 50%</expectedResult> <actualResult type="variable">DropDownTierPriceTextProduct1</actualResult> </assertContains> <!-- Check Tier Prices for product 2 --> - <selectOption selector="{{StorefrontBundledSection.dropDownOptionOneProducts('Drop-down Option')}}" userInput="$$simpleProduct2.sku$$ +$$$simpleProduct2.price$$.00" stepKey="selectDropDownOptionProduct2"/> - <seeOptionIsSelected selector="{{StorefrontBundledSection.dropDownOptionOneProducts('Drop-down Option')}}" userInput="$$simpleProduct2.sku$$ +$$$simpleProduct2.price$$.00" stepKey="checkDropDownOptionProduct2"/> - <grabTextFrom selector="{{StorefrontBundledSection.dropDownOptionTierPrices('Drop-down Option')}}" stepKey="DropDownTierPriceTextProduct2"/> + <selectOption selector="{{StorefrontBundledSection.dropDownOptionOneProducts('Drop-down Option')}}" userInput="$$simpleProduct2CreateBundleProduct.sku$$ +$$$simpleProduct2CreateBundleProduct.price$$.00" stepKey="selectDropDownOptionProduct2"/> + <seeOptionIsSelected selector="{{StorefrontBundledSection.dropDownOptionOneProducts('Drop-down Option')}}" userInput="$$simpleProduct2CreateBundleProduct.sku$$ +$$$simpleProduct2CreateBundleProduct.price$$.00" stepKey="checkDropDownOptionProduct2"/> + <grabTextFrom selector="{{StorefrontBundledSection.dropDownOptionTierPrices('Drop-down Option')}}" stepKey="dropDownTierPriceTextProduct2"/> <assertContains stepKey="assertDropDownTierPriceTextProduct2"> <expectedResult type="string">Buy 7 for $15.00 each and save 25%</expectedResult> - <actualResult type="variable">DropDownTierPriceTextProduct2</actualResult> + <actualResult type="variable">dropDownTierPriceTextProduct2</actualResult> </assertContains> <!--"Radio Buttons" type option--> <!-- Check Tier Prices for product 1 --> - <grabTextFrom selector="{{StorefrontBundledSection.radioButtonOptionLabel('Radio Buttons Option', '$$simpleProduct1.sku$$')}}" stepKey="RadioButtonsOptionTierPriceTextProduct1"/> + <grabTextFrom selector="{{StorefrontBundledSection.radioButtonOptionLabel('Radio Buttons Option', '$$simpleProduct1CreateBundleProduct.sku$$')}}" stepKey="radioButtonsOptionTierPriceTextProduct1"/> <assertContains stepKey="assertRadioButtonsOptionTierPriceTextProduct1"> <expectedResult type="string">Buy 5 for $5.00 each and save 50%</expectedResult> - <actualResult type="variable">RadioButtonsOptionTierPriceTextProduct1</actualResult> + <actualResult type="variable">radioButtonsOptionTierPriceTextProduct1</actualResult> </assertContains> <!-- Check Tier Prices for product 2 --> - <grabTextFrom selector="{{StorefrontBundledSection.radioButtonOptionLabel('Radio Buttons Option', '$$simpleProduct2.sku$$')}}" stepKey="RadioButtonsOptionTierPriceTextProduct2"/> + <grabTextFrom selector="{{StorefrontBundledSection.radioButtonOptionLabel('Radio Buttons Option', '$$simpleProduct2CreateBundleProduct.sku$$')}}" stepKey="radioButtonsOptionTierPriceTextProduct2"/> <assertContains stepKey="assertRadioButtonsOptionTierPriceTextProduct2"> <expectedResult type="string">Buy 7 for $15.00 each and save 25%</expectedResult> - <actualResult type="variable">RadioButtonsOptionTierPriceTextProduct2</actualResult> + <actualResult type="variable">radioButtonsOptionTierPriceTextProduct2</actualResult> </assertContains> <!--"Checkbox" type option--> <!-- Check Tier Prices for product 1 --> - <grabTextFrom selector="{{StorefrontBundledSection.checkboxOptionLabel('Checkbox Option', '$$simpleProduct1.sku$$')}}" stepKey="CheckBoxOptionTierPriceTextProduct1"/> + <grabTextFrom selector="{{StorefrontBundledSection.checkboxOptionLabel('Checkbox Option', '$$simpleProduct1CreateBundleProduct.sku$$')}}" stepKey="checkBoxOptionTierPriceTextProduct1"/> <assertContains stepKey="assertCheckBoxOptionTierPriceTextProduct1"> <expectedResult type="string">Buy 5 for $5.00 each and save 50%</expectedResult> - <actualResult type="variable">CheckBoxOptionTierPriceTextProduct1</actualResult> + <actualResult type="variable">checkBoxOptionTierPriceTextProduct1</actualResult> </assertContains> <!-- Check Tier Prices for product 2 --> - <grabTextFrom selector="{{StorefrontBundledSection.checkboxOptionLabel('Checkbox Option', '$$simpleProduct2.sku$$')}}" stepKey="CheckBoxOptionTierPriceTextProduct2"/> + <grabTextFrom selector="{{StorefrontBundledSection.checkboxOptionLabel('Checkbox Option', '$$simpleProduct2CreateBundleProduct.sku$$')}}" stepKey="checkBoxOptionTierPriceTextProduct2"/> <assertContains stepKey="assertCheckBoxOptionTierPriceTextProduct2"> <expectedResult type="string">Buy 7 for $15.00 each and save 25%</expectedResult> - <actualResult type="variable">CheckBoxOptionTierPriceTextProduct2</actualResult> + <actualResult type="variable">checkBoxOptionTierPriceTextProduct2</actualResult> </assertContains> </test> </tests> diff --git a/app/code/Magento/Bundle/Test/Unit/Block/DataProviders/OptionPriceRendererTest.php b/app/code/Magento/Bundle/Test/Unit/Block/DataProviders/OptionPriceRendererTest.php index 657803fbb3e2b..320ed7888e8c6 100644 --- a/app/code/Magento/Bundle/Test/Unit/Block/DataProviders/OptionPriceRendererTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Block/DataProviders/OptionPriceRendererTest.php @@ -48,26 +48,45 @@ protected function setUp() ); } - public function testRenderTierPrice() + /** + * Test to render Tier price html + * + * @param bool $priceRenderExist + * @param string $expectedHtml + * @dataProvider renderTierPriceDataProvider + */ + public function testRenderTierPrice(bool $priceRenderExist, string $expectedHtml): void { - $tierPriceHtml = 'tier price html'; + $priceRenderer = false; $expectedArguments = ['zone' => Render::ZONE_ITEM_OPTION]; - $productMock = $this->createMock(Product::class); - $blockMock = $this->createPartialMock(BlockInterface::class, ['toHtml', 'render']); - $blockMock->expects($this->once()) - ->method('render') - ->with('tier_price', $productMock, $expectedArguments) - ->willReturn($tierPriceHtml); + + if ($priceRenderExist) { + $priceRenderer = $this->createPartialMock(BlockInterface::class, ['toHtml', 'render']); + $priceRenderer->expects($this->once()) + ->method('render') + ->with('tier_price', $productMock, $expectedArguments) + ->willReturn($expectedHtml); + } $this->layoutMock->method('getBlock') ->with('product.price.render.default') - ->willReturn($blockMock); + ->willReturn($priceRenderer); $this->assertEquals( - $tierPriceHtml, + $expectedHtml, $this->renderer->renderTierPrice($productMock), 'Render Tier price is wrong' ); } + + /** + * Data provider for test to render Tier price + * + * @return array + */ + public function renderTierPriceDataProvider(): array + { + return [[true, 'tier price html'], [false, '']]; + } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php index b97c1f0208b40..30f0978480701 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php @@ -7,13 +7,11 @@ require __DIR__ . '/../../../Magento/Catalog/_files/product_simple.php'; -/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ -$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); -$simpleProduct = $productRepository->get('simple'); - -/** @var $product \Magento\Catalog\Model\Product */ -$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); -$product->setTypeId('bundle') +/** @var $productFactory Magento\Catalog\Model\ProductFactory */ +$productFactory = $objectManager->create(\Magento\Catalog\Model\ProductFactory::class); +/** @var $bundleProduct \Magento\Catalog\Model\Product */ +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId('bundle') ->setAttributeSetId($product->getDefaultAttributeSetId()) ->setWebsiteIds([1]) ->setPriceType(\Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC) @@ -22,7 +20,12 @@ ->setSku('bundle-product') ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setStockData([ + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 1, + ]) ->setBundleOptionsData( [ [ @@ -35,6 +38,6 @@ ] ) ->setBundleSelectionsData( - [[['product_id' => $simpleProduct->getId(), 'selection_qty' => 1, 'delete' => '']]] + [[['product_id' => $product->getId(), 'selection_qty' => 1, 'delete' => '']]] ); -$productRepository->save($product); +$productRepository->save($bundleProduct); From c0255a1521c2ee3ea2471f2a78f0c845a8d0457b Mon Sep 17 00:00:00 2001 From: Ivan Gerchak <ivang@ven.com> Date: Mon, 1 Apr 2019 12:50:17 +0300 Subject: [PATCH 290/603] Remove fotorama.min.js --- lib/web/fotorama/fotorama.min.js | 1 - 1 file changed, 1 deletion(-) delete mode 100644 lib/web/fotorama/fotorama.min.js diff --git a/lib/web/fotorama/fotorama.min.js b/lib/web/fotorama/fotorama.min.js deleted file mode 100644 index 0a0cbd9db7e74..0000000000000 --- a/lib/web/fotorama/fotorama.min.js +++ /dev/null @@ -1 +0,0 @@ -fotoramaVersion="4.6.4";(function(window,document,location,$,undefined){"use strict";var _fotoramaClass="fotorama",_fullscreenClass="fotorama__fullscreen",wrapClass=_fotoramaClass+"__wrap",wrapCss2Class=wrapClass+"--css2",wrapCss3Class=wrapClass+"--css3",wrapVideoClass=wrapClass+"--video",wrapFadeClass=wrapClass+"--fade",wrapSlideClass=wrapClass+"--slide",wrapNoControlsClass=wrapClass+"--no-controls",wrapNoShadowsClass=wrapClass+"--no-shadows",wrapPanYClass=wrapClass+"--pan-y",wrapRtlClass=wrapClass+"--rtl",wrapOnlyActiveClass=wrapClass+"--only-active",wrapNoCaptionsClass=wrapClass+"--no-captions",wrapToggleArrowsClass=wrapClass+"--toggle-arrows",stageClass=_fotoramaClass+"__stage",stageFrameClass=stageClass+"__frame",stageFrameVideoClass=stageFrameClass+"--video",stageShaftClass=stageClass+"__shaft",grabClass=_fotoramaClass+"__grab",pointerClass=_fotoramaClass+"__pointer",arrClass=_fotoramaClass+"__arr",arrDisabledClass=arrClass+"--disabled",arrPrevClass=arrClass+"--prev",arrNextClass=arrClass+"--next",navClass=_fotoramaClass+"__nav",navWrapClass=navClass+"-wrap",navShaftClass=navClass+"__shaft",navShaftVerticalClass=navWrapClass+"--vertical",navShaftListClass=navWrapClass+"--list",navShafthorizontalClass=navWrapClass+"--horizontal",navDotsClass=navClass+"--dots",navThumbsClass=navClass+"--thumbs",navFrameClass=navClass+"__frame",fadeClass=_fotoramaClass+"__fade",fadeFrontClass=fadeClass+"-front",fadeRearClass=fadeClass+"-rear",shadowClass=_fotoramaClass+"__shadow",shadowsClass=shadowClass+"s",shadowsLeftClass=shadowsClass+"--left",shadowsRightClass=shadowsClass+"--right",shadowsTopClass=shadowsClass+"--top",shadowsBottomClass=shadowsClass+"--bottom",activeClass=_fotoramaClass+"__active",selectClass=_fotoramaClass+"__select",hiddenClass=_fotoramaClass+"--hidden",fullscreenClass=_fotoramaClass+"--fullscreen",fullscreenIconClass=_fotoramaClass+"__fullscreen-icon",errorClass=_fotoramaClass+"__error",loadingClass=_fotoramaClass+"__loading",loadedClass=_fotoramaClass+"__loaded",loadedFullClass=loadedClass+"--full",loadedImgClass=loadedClass+"--img",grabbingClass=_fotoramaClass+"__grabbing",imgClass=_fotoramaClass+"__img",imgFullClass=imgClass+"--full",thumbClass=_fotoramaClass+"__thumb",thumbArrLeft=thumbClass+"__arr--left",thumbArrRight=thumbClass+"__arr--right",thumbBorderClass=thumbClass+"-border",htmlClass=_fotoramaClass+"__html",videoContainerClass=_fotoramaClass+"-video-container",videoClass=_fotoramaClass+"__video",videoPlayClass=videoClass+"-play",videoCloseClass=videoClass+"-close",horizontalImageClass=_fotoramaClass+"_horizontal_ratio",verticalImageClass=_fotoramaClass+"_vertical_ratio",fotoramaSpinnerClass=_fotoramaClass+"__spinner",spinnerShowClass=fotoramaSpinnerClass+"--show";var JQUERY_VERSION=$&&$.fn.jquery.split(".");if(!JQUERY_VERSION||JQUERY_VERSION[0]<1||JQUERY_VERSION[0]==1&&JQUERY_VERSION[1]<8){throw"Fotorama requires jQuery 1.8 or later and will not run without it."}var _={};var Modernizr=function(window,document,undefined){var version="2.8.3",Modernizr={},docElement=document.documentElement,mod="modernizr",modElem=document.createElement(mod),mStyle=modElem.style,inputElem,toString={}.toString,prefixes=" -webkit- -moz- -o- -ms- ".split(" "),omPrefixes="Webkit Moz O ms",cssomPrefixes=omPrefixes.split(" "),domPrefixes=omPrefixes.toLowerCase().split(" "),tests={},inputs={},attrs={},classes=[],slice=classes.slice,featureName,injectElementWithStyles=function(rule,callback,nodes,testnames){var style,ret,node,docOverflow,div=document.createElement("div"),body=document.body,fakeBody=body||document.createElement("body");if(parseInt(nodes,10)){while(nodes--){node=document.createElement("div");node.id=testnames?testnames[nodes]:mod+(nodes+1);div.appendChild(node)}}style=["­",'<style id="s',mod,'">',rule,"</style>"].join("");div.id=mod;(body?div:fakeBody).innerHTML+=style;fakeBody.appendChild(div);if(!body){fakeBody.style.background="";fakeBody.style.overflow="hidden";docOverflow=docElement.style.overflow;docElement.style.overflow="hidden";docElement.appendChild(fakeBody)}ret=callback(div,rule);if(!body){fakeBody.parentNode.removeChild(fakeBody);docElement.style.overflow=docOverflow}else{div.parentNode.removeChild(div)}return!!ret},_hasOwnProperty={}.hasOwnProperty,hasOwnProp;if(!is(_hasOwnProperty,"undefined")&&!is(_hasOwnProperty.call,"undefined")){hasOwnProp=function(object,property){return _hasOwnProperty.call(object,property)}}else{hasOwnProp=function(object,property){return property in object&&is(object.constructor.prototype[property],"undefined")}}if(!Function.prototype.bind){Function.prototype.bind=function bind(that){var target=this;if(typeof target!="function"){throw new TypeError}var args=slice.call(arguments,1),bound=function(){if(this instanceof bound){var F=function(){};F.prototype=target.prototype;var self=new F;var result=target.apply(self,args.concat(slice.call(arguments)));if(Object(result)===result){return result}return self}else{return target.apply(that,args.concat(slice.call(arguments)))}};return bound}}function setCss(str){mStyle.cssText=str}function setCssAll(str1,str2){return setCss(prefixes.join(str1+";")+(str2||""))}function is(obj,type){return typeof obj===type}function contains(str,substr){return!!~(""+str).indexOf(substr)}function testProps(props,prefixed){for(var i in props){var prop=props[i];if(!contains(prop,"-")&&mStyle[prop]!==undefined){return prefixed=="pfx"?prop:true}}return false}function testDOMProps(props,obj,elem){for(var i in props){var item=obj[props[i]];if(item!==undefined){if(elem===false)return props[i];if(is(item,"function")){return item.bind(elem||obj)}return item}}return false}function testPropsAll(prop,prefixed,elem){var ucProp=prop.charAt(0).toUpperCase()+prop.slice(1),props=(prop+" "+cssomPrefixes.join(ucProp+" ")+ucProp).split(" ");if(is(prefixed,"string")||is(prefixed,"undefined")){return testProps(props,prefixed)}else{props=(prop+" "+domPrefixes.join(ucProp+" ")+ucProp).split(" ");return testDOMProps(props,prefixed,elem)}}tests["touch"]=function(){var bool;if("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch){bool=true}else{injectElementWithStyles(["@media (",prefixes.join("touch-enabled),("),mod,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(node){bool=node.offsetTop===9})}return bool};tests["csstransforms3d"]=function(){var ret=!!testPropsAll("perspective");if(ret&&"webkitPerspective"in docElement.style){injectElementWithStyles("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(node,rule){ret=node.offsetLeft===9&&node.offsetHeight===3})}return ret};tests["csstransitions"]=function(){return testPropsAll("transition")};for(var feature in tests){if(hasOwnProp(tests,feature)){featureName=feature.toLowerCase();Modernizr[featureName]=tests[feature]();classes.push((Modernizr[featureName]?"":"no-")+featureName)}}Modernizr.addTest=function(feature,test){if(typeof feature=="object"){for(var key in feature){if(hasOwnProp(feature,key)){Modernizr.addTest(key,feature[key])}}}else{feature=feature.toLowerCase();if(Modernizr[feature]!==undefined){return Modernizr}test=typeof test=="function"?test():test;if(typeof enableClasses!=="undefined"&&enableClasses){docElement.className+=" "+(test?"":"no-")+feature}Modernizr[feature]=test}return Modernizr};setCss("");modElem=inputElem=null;Modernizr._version=version;Modernizr._prefixes=prefixes;Modernizr._domPrefixes=domPrefixes;Modernizr._cssomPrefixes=cssomPrefixes;Modernizr.testProp=function(prop){return testProps([prop])};Modernizr.testAllProps=testPropsAll;Modernizr.testStyles=injectElementWithStyles;Modernizr.prefixed=function(prop,obj,elem){if(!obj){return testPropsAll(prop,"pfx")}else{return testPropsAll(prop,obj,elem)}};return Modernizr}(window,document);var fullScreenApi={ok:false,is:function(){return false},request:function(){},cancel:function(){},event:"",prefix:""},browserPrefixes="webkit moz o ms khtml".split(" ");if(typeof document.cancelFullScreen!="undefined"){fullScreenApi.ok=true}else{for(var i=0,il=browserPrefixes.length;i<il;i++){fullScreenApi.prefix=browserPrefixes[i];if(typeof document[fullScreenApi.prefix+"CancelFullScreen"]!="undefined"){fullScreenApi.ok=true;break}}}if(fullScreenApi.ok){fullScreenApi.event=fullScreenApi.prefix+"fullscreenchange";fullScreenApi.is=function(){switch(this.prefix){case"":return document.fullScreen;case"webkit":return document.webkitIsFullScreen;default:return document[this.prefix+"FullScreen"]}};fullScreenApi.request=function(el){return this.prefix===""?el.requestFullScreen():el[this.prefix+"RequestFullScreen"]()};fullScreenApi.cancel=function(el){return this.prefix===""?document.cancelFullScreen():document[this.prefix+"CancelFullScreen"]()}}function bez(coOrdArray){var encodedFuncName="bez_"+$.makeArray(arguments).join("_").replace(".","p");if(typeof $["easing"][encodedFuncName]!=="function"){var polyBez=function(p1,p2){var A=[null,null],B=[null,null],C=[null,null],bezCoOrd=function(t,ax){C[ax]=3*p1[ax];B[ax]=3*(p2[ax]-p1[ax])-C[ax];A[ax]=1-C[ax]-B[ax];return t*(C[ax]+t*(B[ax]+t*A[ax]))},xDeriv=function(t){return C[0]+t*(2*B[0]+3*A[0]*t)},xForT=function(t){var x=t,i=0,z;while(++i<14){z=bezCoOrd(x,0)-t;if(Math.abs(z)<.001)break;x-=z/xDeriv(x)}return x};return function(t){return bezCoOrd(xForT(t),1)}};$["easing"][encodedFuncName]=function(x,t,b,c,d){return c*polyBez([coOrdArray[0],coOrdArray[1]],[coOrdArray[2],coOrdArray[3]])(t/d)+b}}return encodedFuncName}var $WINDOW=$(window),$DOCUMENT=$(document),$HTML,$BODY,QUIRKS_FORCE=location.hash.replace("#","")==="quirks",TRANSFORMS3D=Modernizr.csstransforms3d,CSS3=TRANSFORMS3D&&!QUIRKS_FORCE,COMPAT=TRANSFORMS3D||document.compatMode==="CSS1Compat",FULLSCREEN=fullScreenApi.ok,MOBILE=navigator.userAgent.match(/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i),SLOW=!CSS3||MOBILE,MS_POINTER=navigator.msPointerEnabled,WHEEL="onwheel"in document.createElement("div")?"wheel":document.onmousewheel!==undefined?"mousewheel":"DOMMouseScroll",TOUCH_TIMEOUT=250,TRANSITION_DURATION=300,SCROLL_LOCK_TIMEOUT=1400,AUTOPLAY_INTERVAL=5e3,MARGIN=2,THUMB_SIZE=64,WIDTH=500,HEIGHT=333,STAGE_FRAME_KEY="$stageFrame",NAV_DOT_FRAME_KEY="$navDotFrame",NAV_THUMB_FRAME_KEY="$navThumbFrame",AUTO="auto",BEZIER=bez([.1,0,.25,1]),MAX_WIDTH=1200,thumbsPerSlide=1,OPTIONS={width:null,minwidth:null,maxwidth:"100%",height:null,minheight:null,maxheight:null,ratio:null,margin:MARGIN,nav:"dots",navposition:"bottom",navwidth:null,thumbwidth:THUMB_SIZE,thumbheight:THUMB_SIZE,thumbmargin:MARGIN,thumbborderwidth:MARGIN,allowfullscreen:false,transition:"slide",clicktransition:null,transitionduration:TRANSITION_DURATION,captions:true,startindex:0,loop:false,autoplay:false,stopautoplayontouch:true,keyboard:false,arrows:true,click:true,swipe:false,trackpad:false,shuffle:false,direction:"ltr",shadows:true,showcaption:true,navdir:"horizontal",navarrows:true,navtype:"thumbs"},KEYBOARD_OPTIONS={left:true,right:true,down:true,up:true,space:false,home:false,end:false};function noop(){}function minMaxLimit(value,min,max){return Math.max(isNaN(min)?-Infinity:min,Math.min(isNaN(max)?Infinity:max,value))}function readTransform(css,dir){return css.match(/ma/)&&css.match(/-?\d+(?!d)/g)[css.match(/3d/)?dir==="vertical"?13:12:dir==="vertical"?5:4]}function readPosition($el,dir){if(CSS3){return+readTransform($el.css("transform"),dir)}else{return+$el.css(dir==="vertical"?"top":"left").replace("px","")}}function getTranslate(pos,direction){var obj={};if(CSS3){switch(direction){case"vertical":obj.transform="translate3d(0, "+pos+"px,0)";break;case"list":break;default:obj.transform="translate3d("+pos+"px,0,0)";break}}else{direction==="vertical"?obj.top=pos:obj.left=pos}return obj}function getDuration(time){return{"transition-duration":time+"ms"}}function unlessNaN(value,alternative){return isNaN(value)?alternative:value}function numberFromMeasure(value,measure){return unlessNaN(+String(value).replace(measure||"px",""))}function numberFromPercent(value){return/%$/.test(value)?numberFromMeasure(value,"%"):undefined}function numberFromWhatever(value,whole){return unlessNaN(numberFromPercent(value)/100*whole,numberFromMeasure(value))}function measureIsValid(value){return(!isNaN(numberFromMeasure(value))||!isNaN(numberFromMeasure(value,"%")))&&value}function getPosByIndex(index,side,margin,baseIndex){return(index-(baseIndex||0))*(side+(margin||0))}function getIndexByPos(pos,side,margin,baseIndex){return-Math.round(pos/(side+(margin||0))-(baseIndex||0))}function bindTransitionEnd($el){var elData=$el.data();if(elData.tEnd)return;var el=$el[0],transitionEndEvent={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",msTransition:"MSTransitionEnd",transition:"transitionend"};addEvent(el,transitionEndEvent[Modernizr.prefixed("transition")],function(e){elData.tProp&&e.propertyName.match(elData.tProp)&&elData.onEndFn()});elData.tEnd=true}function afterTransition($el,property,fn,time){var ok,elData=$el.data();if(elData){elData.onEndFn=function(){if(ok)return;ok=true;clearTimeout(elData.tT);fn()};elData.tProp=property;clearTimeout(elData.tT);elData.tT=setTimeout(function(){elData.onEndFn()},time*1.5);bindTransitionEnd($el)}}function stop($el,pos){var dir=$el.navdir||"horizontal";if($el.length){var elData=$el.data();if(CSS3){$el.css(getDuration(0));elData.onEndFn=noop;clearTimeout(elData.tT)}else{$el.stop()}var lockedPos=getNumber(pos,function(){return readPosition($el,dir)});$el.css(getTranslate(lockedPos,dir));return lockedPos}}function getNumber(){var number;for(var _i=0,_l=arguments.length;_i<_l;_i++){number=_i?arguments[_i]():arguments[_i];if(typeof number==="number"){break}}return number}function edgeResistance(pos,edge){return Math.round(pos+(edge-pos)/1.5)}function getProtocol(){getProtocol.p=getProtocol.p||(location.protocol==="https:"?"https://":"http://");return getProtocol.p}function parseHref(href){var a=document.createElement("a");a.href=href;return a}function findVideoId(href,forceVideo){if(typeof href!=="string")return href;href=parseHref(href);var id,type;if(href.host.match(/youtube\.com/)&&href.search){id=href.search.split("v=")[1];if(id){var ampersandPosition=id.indexOf("&");if(ampersandPosition!==-1){id=id.substring(0,ampersandPosition)}type="youtube"}}else if(href.host.match(/youtube\.com|youtu\.be/)){id=href.pathname.replace(/^\/(embed\/|v\/)?/,"").replace(/\/.*/,"");type="youtube"}else if(href.host.match(/vimeo\.com/)){type="vimeo";id=href.pathname.replace(/^\/(video\/)?/,"").replace(/\/.*/,"")}if((!id||!type)&&forceVideo){id=href.href;type="custom"}return id?{id:id,type:type,s:href.search.replace(/^\?/,""),p:getProtocol()}:false}function getVideoThumbs(dataFrame,data,fotorama){var img,thumb,video=dataFrame.video;if(video.type==="youtube"){thumb=getProtocol()+"img.youtube.com/vi/"+video.id+"/default.jpg";img=thumb.replace(/\/default.jpg$/,"/hqdefault.jpg");dataFrame.thumbsReady=true}else if(video.type==="vimeo"){$.ajax({url:getProtocol()+"vimeo.com/api/v2/video/"+video.id+".json",dataType:"jsonp",success:function(json){dataFrame.thumbsReady=true;updateData(data,{img:json[0].thumbnail_large,thumb:json[0].thumbnail_small},dataFrame.i,fotorama)}})}else{dataFrame.thumbsReady=true}return{img:img,thumb:thumb}}function updateData(data,_dataFrame,i,fotorama){for(var _i=0,_l=data.length;_i<_l;_i++){var dataFrame=data[_i];if(dataFrame.i===i&&dataFrame.thumbsReady){var clear={videoReady:true};clear[STAGE_FRAME_KEY]=clear[NAV_THUMB_FRAME_KEY]=clear[NAV_DOT_FRAME_KEY]=false;fotorama.splice(_i,1,$.extend({},dataFrame,clear,_dataFrame));break}}}function getDataFromHtml($el){var data=[];function getDataFromImg($img,imgData,checkVideo){var $child=$img.children("img").eq(0),_imgHref=$img.attr("href"),_imgSrc=$img.attr("src"),_thumbSrc=$child.attr("src"),_video=imgData.video,video=checkVideo?findVideoId(_imgHref,_video===true):false;if(video){_imgHref=false}else{video=_video}getDimensions($img,$child,$.extend(imgData,{video:video,img:imgData.img||_imgHref||_imgSrc||_thumbSrc,thumb:imgData.thumb||_thumbSrc||_imgSrc||_imgHref}))}function getDimensions($img,$child,imgData){var separateThumbFLAG=imgData.thumb&&imgData.img!==imgData.thumb,width=numberFromMeasure(imgData.width||$img.attr("width")),height=numberFromMeasure(imgData.height||$img.attr("height"));$.extend(imgData,{width:width,height:height,thumbratio:getRatio(imgData.thumbratio||numberFromMeasure(imgData.thumbwidth||$child&&$child.attr("width")||separateThumbFLAG||width)/numberFromMeasure(imgData.thumbheight||$child&&$child.attr("height")||separateThumbFLAG||height))})}$el.children().each(function(){var $this=$(this),dataFrame=optionsToLowerCase($.extend($this.data(),{id:$this.attr("id")}));if($this.is("a, img")){getDataFromImg($this,dataFrame,true)}else if(!$this.is(":empty")){getDimensions($this,null,$.extend(dataFrame,{html:this,_html:$this.html()}))}else return;data.push(dataFrame)});return data}function isHidden(el){return el.offsetWidth===0&&el.offsetHeight===0}function isDetached(el){return!$.contains(document.documentElement,el)}function waitFor(test,fn,timeout,i){if(!waitFor.i){waitFor.i=1;waitFor.ii=[true]}i=i||waitFor.i;if(typeof waitFor.ii[i]==="undefined"){waitFor.ii[i]=true}if(test()){fn()}else{waitFor.ii[i]&&setTimeout(function(){waitFor.ii[i]&&waitFor(test,fn,timeout,i)},timeout||100)}return waitFor.i++}waitFor.stop=function(i){waitFor.ii[i]=false};function fit($el,measuresToFit){var elData=$el.data(),measures=elData.measures;if(measures&&(!elData.l||elData.l.W!==measures.width||elData.l.H!==measures.height||elData.l.r!==measures.ratio||elData.l.w!==measuresToFit.w||elData.l.h!==measuresToFit.h)){var height=minMaxLimit(measuresToFit.h,0,measures.height),width=height*measures.ratio;UTIL.setRatio($el,width,height);elData.l={W:measures.width,H:measures.height,r:measures.ratio,w:measuresToFit.w,h:measuresToFit.h}}return true}function setStyle($el,style){var el=$el[0];if(el.styleSheet){el.styleSheet.cssText=style}else{$el.html(style)}}function findShadowEdge(pos,min,max,dir){return min===max?false:dir==="vertical"?pos<=min?"top":pos>=max?"bottom":"top bottom":pos<=min?"left":pos>=max?"right":"left right"}function smartClick($el,fn,_options){_options=_options||{};$el.each(function(){var $this=$(this),thisData=$this.data(),startEvent;if(thisData.clickOn)return;thisData.clickOn=true;$.extend(touch($this,{onStart:function(e){startEvent=e;(_options.onStart||noop).call(this,e)},onMove:_options.onMove||noop,onTouchEnd:_options.onTouchEnd||noop,onEnd:function(result){if(result.moved)return;fn.call(this,startEvent)}}),{noMove:true})})}function div(classes,child){return'<div class="'+classes+'">'+(child||"")+"</div>"}function cls(className){return"."+className}function createVideoFrame(videoItem){var frame='<iframe src="'+videoItem.p+videoItem.type+".com/embed/"+videoItem.id+'" frameborder="0" allowfullscreen></iframe>';return frame}function shuffle(array){var l=array.length;while(l){var i=Math.floor(Math.random()*l--);var t=array[l];array[l]=array[i];array[i]=t}return array}function clone(array){return Object.prototype.toString.call(array)=="[object Array]"&&$.map(array,function(frame){return $.extend({},frame)})}function lockScroll($el,left,top){$el.scrollLeft(left||0).scrollTop(top||0)}function optionsToLowerCase(options){if(options){var opts={};$.each(options,function(key,value){opts[key.toLowerCase()]=value});return opts}}function getRatio(_ratio){if(!_ratio)return;var ratio=+_ratio;if(!isNaN(ratio)){return ratio}else{ratio=_ratio.split("/");return+ratio[0]/+ratio[1]||undefined}}function addEvent(el,e,fn,bool){if(!e)return;el.addEventListener?el.addEventListener(e,fn,!!bool):el.attachEvent("on"+e,fn)}function validateRestrictions(position,restriction){if(position>restriction.max){position=restriction.max}else{if(position<restriction.min){position=restriction.min}}return position}function validateSlidePos(opt,navShaftTouchTail,guessIndex,offsetNav,$guessNavFrame,$navWrap,dir){var position,size,wrapSize;if(dir==="horizontal"){size=opt.thumbwidth;wrapSize=$navWrap.width()}else{size=opt.thumbheight;wrapSize=$navWrap.height()}if((size+opt.margin)*(guessIndex+1)>=wrapSize-offsetNav){if(dir==="horizontal"){position=-$guessNavFrame.position().left}else{position=-$guessNavFrame.position().top}}else{if((size+opt.margin)*guessIndex<=Math.abs(offsetNav)){if(dir==="horizontal"){position=-$guessNavFrame.position().left+wrapSize-(size+opt.margin)}else{position=-$guessNavFrame.position().top+wrapSize-(size+opt.margin)}}else{position=offsetNav}}position=validateRestrictions(position,navShaftTouchTail);return position||0}function elIsDisabled(el){return!!el.getAttribute("disabled")}function disableAttr(FLAG,disable){if(disable){return{disabled:FLAG}}else{return{tabindex:FLAG*-1+"",disabled:FLAG}}}function addEnterUp(el,fn){addEvent(el,"keyup",function(e){elIsDisabled(el)||e.keyCode==13&&fn.call(el,e)})}function addFocus(el,fn){addEvent(el,"focus",el.onfocusin=function(e){fn.call(el,e)},true)}function stopEvent(e,stopPropagation){e.preventDefault?e.preventDefault():e.returnValue=false;stopPropagation&&e.stopPropagation&&e.stopPropagation()}function stubEvent($el,eventType){var isIOS=/ip(ad|hone|od)/i.test(window.navigator.userAgent);if(isIOS&&eventType==="touchend"){$el.on("touchend",function(e){$DOCUMENT.trigger("mouseup",e)})}$el.on(eventType,function(e){stopEvent(e,true);return false})}function getDirectionSign(forward){return forward?">":"<"}var UTIL=function(){function setRatioClass($el,wh,ht){var rateImg=wh/ht;if(rateImg<=1){$el.parent().removeClass(horizontalImageClass);$el.parent().addClass(verticalImageClass)}else{$el.parent().removeClass(verticalImageClass);$el.parent().addClass(horizontalImageClass)}}function setThumbAttr($frame,value,searchAttr){var attr=searchAttr;if(!$frame.attr(attr)&&$frame.attr(attr)!==undefined){$frame.attr(attr,value)}if($frame.find("["+attr+"]").length){$frame.find("["+attr+"]").each(function(){$(this).attr(attr,value)})}}function isExpectedCaption(frameItem,isExpected,undefined){var expected=false,frameExpected;frameItem.showCaption===undefined||frameItem.showCaption===true?frameExpected=true:frameExpected=false;if(!isExpected){return false}if(frameItem.caption&&frameExpected){expected=true}return expected}return{setRatio:setRatioClass,setThumbAttr:setThumbAttr,isExpectedCaption:isExpectedCaption}}(UTIL||{},jQuery);function slide($el,options){var elData=$el.data(),elPos=Math.round(options.pos),onEndFn=function(){if(elData&&elData.sliding){elData.sliding=false}(options.onEnd||noop)()};if(typeof options.overPos!=="undefined"&&options.overPos!==options.pos){elPos=options.overPos}var translate=$.extend(getTranslate(elPos,options.direction),options.width&&{width:options.width},options.height&&{height:options.height});if(elData&&elData.sliding){elData.sliding=true}if(CSS3){$el.css($.extend(getDuration(options.time),translate));if(options.time>10){afterTransition($el,"transform",onEndFn,options.time)}else{onEndFn()}}else{$el.stop().animate(translate,options.time,BEZIER,onEndFn)}}function fade($el1,$el2,$frames,options,fadeStack,chain){var chainedFLAG=typeof chain!=="undefined";if(!chainedFLAG){fadeStack.push(arguments);Array.prototype.push.call(arguments,fadeStack.length);if(fadeStack.length>1)return}$el1=$el1||$($el1);$el2=$el2||$($el2);var _$el1=$el1[0],_$el2=$el2[0],crossfadeFLAG=options.method==="crossfade",onEndFn=function(){if(!onEndFn.done){onEndFn.done=true;var args=(chainedFLAG||fadeStack.shift())&&fadeStack.shift();args&&fade.apply(this,args);(options.onEnd||noop)(!!args)}},time=options.time/(chain||1);$frames.removeClass(fadeRearClass+" "+fadeFrontClass);$el1.stop().addClass(fadeRearClass);$el2.stop().addClass(fadeFrontClass);crossfadeFLAG&&_$el2&&$el1.fadeTo(0,0);$el1.fadeTo(crossfadeFLAG?time:0,1,crossfadeFLAG&&onEndFn);$el2.fadeTo(time,0,onEndFn);_$el1&&crossfadeFLAG||_$el2||onEndFn()}var lastEvent,moveEventType,preventEvent,preventEventTimeout,dragDomEl;function extendEvent(e){var touch=(e.touches||[])[0]||e;e._x=touch.pageX||touch.originalEvent.pageX;e._y=touch.clientY||touch.originalEvent.clientY;e._now=$.now()}function touch($el,options){var el=$el[0],tail={},touchEnabledFLAG,startEvent,$target,controlTouch,touchFLAG,targetIsSelectFLAG,targetIsLinkFlag,tolerance,moved;function onStart(e){$target=$(e.target);tail.checked=targetIsSelectFLAG=targetIsLinkFlag=moved=false;if(touchEnabledFLAG||tail.flow||e.touches&&e.touches.length>1||e.which>1||lastEvent&&lastEvent.type!==e.type&&preventEvent||(targetIsSelectFLAG=options.select&&$target.is(options.select,el)))return targetIsSelectFLAG;touchFLAG=e.type==="touchstart";targetIsLinkFlag=$target.is("a, a *",el);controlTouch=tail.control;tolerance=tail.noMove||tail.noSwipe||controlTouch?16:!tail.snap?4:0;extendEvent(e);startEvent=lastEvent=e;moveEventType=e.type.replace(/down|start/,"move").replace(/Down/,"Move");(options.onStart||noop).call(el,e,{control:controlTouch,$target:$target});touchEnabledFLAG=tail.flow=true;if(!touchFLAG||tail.go)stopEvent(e)}function onMove(e){if(e.touches&&e.touches.length>1||MS_POINTER&&!e.isPrimary||moveEventType!==e.type||!touchEnabledFLAG){touchEnabledFLAG&&onEnd();(options.onTouchEnd||noop)();return}extendEvent(e);var xDiff=Math.abs(e._x-startEvent._x),yDiff=Math.abs(e._y-startEvent._y),xyDiff=xDiff-yDiff,xWin=(tail.go||tail.x||xyDiff>=0)&&!tail.noSwipe,yWin=xyDiff<0;if(touchFLAG&&!tail.checked){if(touchEnabledFLAG=xWin){stopEvent(e)}}else{stopEvent(e);if(movedEnough(xDiff,yDiff)){(options.onMove||noop).call(el,e,{touch:touchFLAG})}}if(!moved&&movedEnough(xDiff,yDiff)&&Math.sqrt(Math.pow(xDiff,2)+Math.pow(yDiff,2))>tolerance){moved=true}tail.checked=tail.checked||xWin||yWin}function movedEnough(xDiff,yDiff){return xDiff>yDiff&&xDiff>1.5}function onEnd(e){(options.onTouchEnd||noop)();var _touchEnabledFLAG=touchEnabledFLAG;tail.control=touchEnabledFLAG=false;if(_touchEnabledFLAG){tail.flow=false}if(!_touchEnabledFLAG||targetIsLinkFlag&&!tail.checked)return;e&&stopEvent(e);preventEvent=true;clearTimeout(preventEventTimeout);preventEventTimeout=setTimeout(function(){preventEvent=false},1e3);(options.onEnd||noop).call(el,{moved:moved,$target:$target,control:controlTouch,touch:touchFLAG,startEvent:startEvent,aborted:!e||e.type==="MSPointerCancel"})}function onOtherStart(){if(tail.flow)return;tail.flow=true}function onOtherEnd(){if(!tail.flow)return;tail.flow=false}if(MS_POINTER){addEvent(el,"MSPointerDown",onStart);addEvent(document,"MSPointerMove",onMove);addEvent(document,"MSPointerCancel",onEnd);addEvent(document,"MSPointerUp",onEnd)}else{addEvent(el,"touchstart",onStart);addEvent(el,"touchmove",onMove);addEvent(el,"touchend",onEnd);addEvent(document,"touchstart",onOtherStart);addEvent(document,"touchend",onOtherEnd);addEvent(document,"touchcancel",onOtherEnd);$WINDOW.on("scroll",onOtherEnd);$el.on("mousedown pointerdown",onStart);$DOCUMENT.on("mousemove pointermove",onMove).on("mouseup pointerup",onEnd)}if(Modernizr.touch){dragDomEl="a"}else{dragDomEl="div"}$el.on("click",dragDomEl,function(e){tail.checked&&stopEvent(e)});return tail}function moveOnTouch($el,options){var el=$el[0],elData=$el.data(),tail={},startCoo,coo,startElPos,moveElPos,edge,moveTrack,startTime,endTime,min,max,snap,dir,slowFLAG,controlFLAG,moved,tracked;function startTracking(e,noStop){tracked=true;startCoo=coo=dir==="vertical"?e._y:e._x;startTime=e._now;moveTrack=[[startTime,startCoo]];startElPos=moveElPos=tail.noMove||noStop?0:stop($el,(options.getPos||noop)());(options.onStart||noop).call(el,e)}function onStart(e,result){min=tail.min;max=tail.max;snap=tail.snap,dir=tail.direction||"horizontal",$el.navdir=dir;slowFLAG=e.altKey;tracked=moved=false;controlFLAG=result.control;if(!controlFLAG&&!elData.sliding){startTracking(e)}}function onMove(e,result){if(!tail.noSwipe){if(!tracked){startTracking(e)}coo=dir==="vertical"?e._y:e._x;moveTrack.push([e._now,coo]);moveElPos=startElPos-(startCoo-coo);edge=findShadowEdge(moveElPos,min,max,dir);if(moveElPos<=min){moveElPos=edgeResistance(moveElPos,min)}else if(moveElPos>=max){moveElPos=edgeResistance(moveElPos,max)}if(!tail.noMove){$el.css(getTranslate(moveElPos,dir));if(!moved){moved=true;result.touch||MS_POINTER||$el.addClass(grabbingClass)}(options.onMove||noop).call(el,e,{pos:moveElPos,edge:edge})}}}function onEnd(result){if(tail.noSwipe&&result.moved)return;if(!tracked){startTracking(result.startEvent,true)}result.touch||MS_POINTER||$el.removeClass(grabbingClass);endTime=$.now();var _backTimeIdeal=endTime-TOUCH_TIMEOUT,_backTime,_timeDiff,_timeDiffLast,backTime=null,backCoo,virtualPos,limitPos,newPos,overPos,time=TRANSITION_DURATION,speed,friction=options.friction;for(var _i=moveTrack.length-1;_i>=0;_i--){_backTime=moveTrack[_i][0];_timeDiff=Math.abs(_backTime-_backTimeIdeal);if(backTime===null||_timeDiff<_timeDiffLast){backTime=_backTime;backCoo=moveTrack[_i][1]}else if(backTime===_backTimeIdeal||_timeDiff>_timeDiffLast){break}_timeDiffLast=_timeDiff}newPos=minMaxLimit(moveElPos,min,max);var cooDiff=backCoo-coo,forwardFLAG=cooDiff>=0,timeDiff=endTime-backTime,longTouchFLAG=timeDiff>TOUCH_TIMEOUT,swipeFLAG=!longTouchFLAG&&moveElPos!==startElPos&&newPos===moveElPos;if(snap){newPos=minMaxLimit(Math[swipeFLAG?forwardFLAG?"floor":"ceil":"round"](moveElPos/snap)*snap,min,max);min=max=newPos}if(swipeFLAG&&(snap||newPos===moveElPos)){speed=-(cooDiff/timeDiff);time*=minMaxLimit(Math.abs(speed),options.timeLow,options.timeHigh);virtualPos=Math.round(moveElPos+speed*time/friction);if(!snap){newPos=virtualPos}if(!forwardFLAG&&virtualPos>max||forwardFLAG&&virtualPos<min){limitPos=forwardFLAG?min:max;overPos=virtualPos-limitPos;if(!snap){newPos=limitPos}overPos=minMaxLimit(newPos+overPos*.03,limitPos-50,limitPos+50);time=Math.abs((moveElPos-overPos)/(speed/friction))}}time*=slowFLAG?10:1;(options.onEnd||noop).call(el,$.extend(result,{moved:result.moved||longTouchFLAG&&snap,pos:moveElPos,newPos:newPos,overPos:overPos,time:time,dir:dir}))}tail=$.extend(touch(options.$wrap,$.extend({},options,{onStart:onStart,onMove:onMove,onEnd:onEnd})),tail);return tail}function wheel($el,options){var el=$el[0],lockFLAG,lastDirection,lastNow,tail={prevent:{}};addEvent(el,WHEEL,function(e){var yDelta=e.wheelDeltaY||-1*e.deltaY||0,xDelta=e.wheelDeltaX||-1*e.deltaX||0,xWin=Math.abs(xDelta)&&!Math.abs(yDelta),direction=getDirectionSign(xDelta<0),sameDirection=lastDirection===direction,now=$.now(),tooFast=now-lastNow<TOUCH_TIMEOUT;lastDirection=direction;lastNow=now;if(!xWin||!tail.ok||tail.prevent[direction]&&!lockFLAG){return}else{stopEvent(e,true);if(lockFLAG&&sameDirection&&tooFast){return}}if(options.shift){lockFLAG=true;clearTimeout(tail.t);tail.t=setTimeout(function(){lockFLAG=false},SCROLL_LOCK_TIMEOUT)}(options.onEnd||noop)(e,options.shift?direction:xDelta)});return tail}jQuery.Fotorama=function($fotorama,opts){$HTML=$("html");$BODY=$("body");var that=this,stamp=$.now(),stampClass=_fotoramaClass+stamp,fotorama=$fotorama[0],data,dataFrameCount=1,fotoramaData=$fotorama.data(),size,$style=$("<style></style>"),$anchor=$(div(hiddenClass)),$wrap=$fotorama.find(cls(wrapClass)),$stage=$wrap.find(cls(stageClass)),stage=$stage[0],$stageShaft=$fotorama.find(cls(stageShaftClass)),$stageFrame=$(),$arrPrev=$fotorama.find(cls(arrPrevClass)),$arrNext=$fotorama.find(cls(arrNextClass)),$arrs=$fotorama.find(cls(arrClass)),$navWrap=$fotorama.find(cls(navWrapClass)),$nav=$navWrap.find(cls(navClass)),$navShaft=$nav.find(cls(navShaftClass)),$navFrame,$navDotFrame=$(),$navThumbFrame=$(),stageShaftData=$stageShaft.data(),navShaftData=$navShaft.data(),$thumbBorder=$fotorama.find(cls(thumbBorderClass)),$thumbArrLeft=$fotorama.find(cls(thumbArrLeft)),$thumbArrRight=$fotorama.find(cls(thumbArrRight)),$fullscreenIcon=$fotorama.find(cls(fullscreenIconClass)),fullscreenIcon=$fullscreenIcon[0],$videoPlay=$(div(videoPlayClass)),$videoClose=$fotorama.find(cls(videoCloseClass)),videoClose=$videoClose[0],$spinner=$fotorama.find(cls(fotoramaSpinnerClass)),$videoPlaying,activeIndex=false,activeFrame,activeIndexes,repositionIndex,dirtyIndex,lastActiveIndex,prevIndex,nextIndex,nextAutoplayIndex,startIndex,o_loop,o_nav,o_navThumbs,o_navTop,o_allowFullScreen,o_nativeFullScreen,o_fade,o_thumbSide,o_thumbSide2,o_transitionDuration,o_transition,o_shadows,o_rtl,o_keyboard,lastOptions={},measures={},measuresSetFLAG,stageShaftTouchTail={},stageWheelTail={},navShaftTouchTail={},navWheelTail={},scrollTop,scrollLeft,showedFLAG,pausedAutoplayFLAG,stoppedAutoplayFLAG,toDeactivate={},toDetach={},measuresStash,touchedFLAG,hoverFLAG,navFrameKey,stageLeft=0,fadeStack=[];$wrap[STAGE_FRAME_KEY]=$('<div class="'+stageFrameClass+'"></div>');$wrap[NAV_THUMB_FRAME_KEY]=$($.Fotorama.jst.thumb());$wrap[NAV_DOT_FRAME_KEY]=$($.Fotorama.jst.dots());toDeactivate[STAGE_FRAME_KEY]=[];toDeactivate[NAV_THUMB_FRAME_KEY]=[];toDeactivate[NAV_DOT_FRAME_KEY]=[];toDetach[STAGE_FRAME_KEY]={};$wrap.addClass(CSS3?wrapCss3Class:wrapCss2Class);fotoramaData.fotorama=this;function checkForVideo(){$.each(data,function(i,dataFrame){if(!dataFrame.i){dataFrame.i=dataFrameCount++;var video=findVideoId(dataFrame.video,true);if(video){var thumbs={};dataFrame.video=video;if(!dataFrame.img&&!dataFrame.thumb){thumbs=getVideoThumbs(dataFrame,data,that)}else{dataFrame.thumbsReady=true}updateData(data,{img:thumbs.img,thumb:thumbs.thumb},dataFrame.i,that)}}})}function allowKey(key){return o_keyboard[key]}function setStagePosition(){if($stage!==undefined){if(opts.navdir=="vertical"){var padding=opts.thumbwidth+opts.thumbmargin;$stage.css("left",padding);$arrNext.css("right",padding);$fullscreenIcon.css("right",padding);$wrap.css("width",$wrap.css("width")+padding);$stageShaft.css("max-width",$wrap.width()-padding)}else{$stage.css("left","");$arrNext.css("right","");$fullscreenIcon.css("right","");$wrap.css("width",$wrap.css("width")+padding);$stageShaft.css("max-width","")}}}function bindGlobalEvents(FLAG){var keydownCommon="keydown."+_fotoramaClass,localStamp=_fotoramaClass+stamp,keydownLocal="keydown."+localStamp,keyupLocal="keyup."+localStamp,resizeLocal="resize."+localStamp+" "+"orientationchange."+localStamp,showParams;if(FLAG){$DOCUMENT.on(keydownLocal,function(e){var catched,index;if($videoPlaying&&e.keyCode===27){catched=true;unloadVideo($videoPlaying,true,true)}else if(that.fullScreen||opts.keyboard&&!that.index){if(e.keyCode===27){catched=true;that.cancelFullScreen()}else if(e.shiftKey&&e.keyCode===32&&allowKey("space")||!e.altKey&&!e.metaKey&&e.keyCode===37&&allowKey("left")||e.keyCode===38&&allowKey("up")&&$(":focus").attr("data-gallery-role")){that.longPress.progress();index="<"}else if(e.keyCode===32&&allowKey("space")||!e.altKey&&!e.metaKey&&e.keyCode===39&&allowKey("right")||e.keyCode===40&&allowKey("down")&&$(":focus").attr("data-gallery-role")){that.longPress.progress();index=">"}else if(e.keyCode===36&&allowKey("home")){that.longPress.progress();index="<<"}else if(e.keyCode===35&&allowKey("end")){that.longPress.progress();index=">>"}}(catched||index)&&stopEvent(e);showParams={index:index,slow:e.altKey,user:true};index&&(that.longPress.inProgress?that.showWhileLongPress(showParams):that.show(showParams))});if(FLAG){$DOCUMENT.on(keyupLocal,function(e){if(that.longPress.inProgress){that.showEndLongPress({user:true})}that.longPress.reset()})}if(!that.index){$DOCUMENT.off(keydownCommon).on(keydownCommon,"textarea, input, select",function(e){!$BODY.hasClass(_fullscreenClass)&&e.stopPropagation()})}$WINDOW.on(resizeLocal,that.resize)}else{$DOCUMENT.off(keydownLocal);$WINDOW.off(resizeLocal)}}function appendElements(FLAG){if(FLAG===appendElements.f)return;if(FLAG){$fotorama.addClass(_fotoramaClass+" "+stampClass).before($anchor).before($style);addInstance(that)}else{$anchor.detach();$style.detach();$fotorama.html(fotoramaData.urtext).removeClass(stampClass);hideInstance(that)}bindGlobalEvents(FLAG);appendElements.f=FLAG}function setData(){data=that.data=data||clone(opts.data)||getDataFromHtml($fotorama);size=that.size=data.length;ready.ok&&opts.shuffle&&shuffle(data);checkForVideo();activeIndex=limitIndex(activeIndex);size&&appendElements(true)}function stageNoMove(){var _noMove=size<2||$videoPlaying;stageShaftTouchTail.noMove=_noMove||o_fade;stageShaftTouchTail.noSwipe=_noMove||!opts.swipe;!o_transition&&$stageShaft.toggleClass(grabClass,!opts.click&&!stageShaftTouchTail.noMove&&!stageShaftTouchTail.noSwipe);MS_POINTER&&$wrap.toggleClass(wrapPanYClass,!stageShaftTouchTail.noSwipe)}function setAutoplayInterval(interval){if(interval===true)interval="";opts.autoplay=Math.max(+interval||AUTOPLAY_INTERVAL,o_transitionDuration*1.5)}function updateThumbArrow(opt){if(opt.navarrows&&opt.nav==="thumbs"){$thumbArrLeft.show();$thumbArrRight.show()}else{$thumbArrLeft.hide();$thumbArrRight.hide()}}function getThumbsInSlide($el,opts){return Math.floor($wrap.width()/(opts.thumbwidth+opts.thumbmargin))}function setOptions(){if(!opts.nav||opts.nav==="dots"){opts.navdir="horizontal"}that.options=opts=optionsToLowerCase(opts);thumbsPerSlide=getThumbsInSlide($wrap,opts);o_fade=opts.transition==="crossfade"||opts.transition==="dissolve";o_loop=opts.loop&&(size>2||o_fade&&(!o_transition||o_transition!=="slide"));o_transitionDuration=+opts.transitionduration||TRANSITION_DURATION;o_rtl=opts.direction==="rtl";o_keyboard=$.extend({},opts.keyboard&&KEYBOARD_OPTIONS,opts.keyboard);updateThumbArrow(opts);var classes={add:[],remove:[]};function addOrRemoveClass(FLAG,value){classes[FLAG?"add":"remove"].push(value)}if(size>1){o_nav=opts.nav;o_navTop=opts.navposition==="top";classes.remove.push(selectClass);$arrs.toggle(!!opts.arrows)}else{o_nav=false;$arrs.hide()}arrsUpdate();stageWheelUpdate();thumbArrUpdate();if(opts.autoplay)setAutoplayInterval(opts.autoplay);o_thumbSide=numberFromMeasure(opts.thumbwidth)||THUMB_SIZE;o_thumbSide2=numberFromMeasure(opts.thumbheight)||THUMB_SIZE;stageWheelTail.ok=navWheelTail.ok=opts.trackpad&&!SLOW;stageNoMove();extendMeasures(opts,[measures]);o_navThumbs=o_nav==="thumbs";if($navWrap.filter(":hidden")&&!!o_nav){$navWrap.show()}if(o_navThumbs){frameDraw(size,"navThumb");$navFrame=$navThumbFrame;navFrameKey=NAV_THUMB_FRAME_KEY;setStyle($style,$.Fotorama.jst.style({w:o_thumbSide,h:o_thumbSide2,b:opts.thumbborderwidth,m:opts.thumbmargin,s:stamp,q:!COMPAT}));$nav.addClass(navThumbsClass).removeClass(navDotsClass)}else if(o_nav==="dots"){frameDraw(size,"navDot");$navFrame=$navDotFrame;navFrameKey=NAV_DOT_FRAME_KEY;$nav.addClass(navDotsClass).removeClass(navThumbsClass)}else{$navWrap.hide();o_nav=false;$nav.removeClass(navThumbsClass+" "+navDotsClass)}if(o_nav){if(o_navTop){$navWrap.insertBefore($stage)}else{$navWrap.insertAfter($stage)}frameAppend.nav=false;frameAppend($navFrame,$navShaft,"nav")}o_allowFullScreen=opts.allowfullscreen;if(o_allowFullScreen){$fullscreenIcon.prependTo($stage);o_nativeFullScreen=FULLSCREEN&&o_allowFullScreen==="native";stubEvent($fullscreenIcon,"touchend")}else{$fullscreenIcon.detach();o_nativeFullScreen=false}addOrRemoveClass(o_fade,wrapFadeClass);addOrRemoveClass(!o_fade,wrapSlideClass);addOrRemoveClass(!opts.captions,wrapNoCaptionsClass);addOrRemoveClass(o_rtl,wrapRtlClass);addOrRemoveClass(opts.arrows,wrapToggleArrowsClass);o_shadows=opts.shadows&&!SLOW;addOrRemoveClass(!o_shadows,wrapNoShadowsClass);$wrap.addClass(classes.add.join(" ")).removeClass(classes.remove.join(" "));lastOptions=$.extend({},opts);setStagePosition()}function normalizeIndex(index){return index<0?(size+index%size)%size:index>=size?index%size:index}function limitIndex(index){return minMaxLimit(index,0,size-1)}function edgeIndex(index){return o_loop?normalizeIndex(index):limitIndex(index)}function getPrevIndex(index){return index>0||o_loop?index-1:false}function getNextIndex(index){return index<size-1||o_loop?index+1:false}function setStageShaftMinmaxAndSnap(){stageShaftTouchTail.min=o_loop?-Infinity:-getPosByIndex(size-1,measures.w,opts.margin,repositionIndex);stageShaftTouchTail.max=o_loop?Infinity:-getPosByIndex(0,measures.w,opts.margin,repositionIndex);stageShaftTouchTail.snap=measures.w+opts.margin}function setNavShaftMinMax(){var isVerticalDir=opts.navdir==="vertical";var param=isVerticalDir?$navShaft.height():$navShaft.width();var mainParam=isVerticalDir?measures.h:measures.nw;navShaftTouchTail.min=Math.min(0,mainParam-param);navShaftTouchTail.max=0;navShaftTouchTail.direction=opts.navdir;$navShaft.toggleClass(grabClass,!(navShaftTouchTail.noMove=navShaftTouchTail.min===navShaftTouchTail.max))}function eachIndex(indexes,type,fn){if(typeof indexes==="number"){indexes=new Array(indexes);var rangeFLAG=true}return $.each(indexes,function(i,index){if(rangeFLAG)index=i;if(typeof index==="number"){var dataFrame=data[normalizeIndex(index)];if(dataFrame){var key="$"+type+"Frame",$frame=dataFrame[key];fn.call(this,i,index,dataFrame,$frame,key,$frame&&$frame.data())}}})}function setMeasures(width,height,ratio,index){if(!measuresSetFLAG||measuresSetFLAG==="*"&&index===startIndex){width=measureIsValid(opts.width)||measureIsValid(width)||WIDTH;height=measureIsValid(opts.height)||measureIsValid(height)||HEIGHT;that.resize({width:width,ratio:opts.ratio||ratio||width/height},0,index!==startIndex&&"*")}}function loadImg(indexes,type,specialMeasures,again){eachIndex(indexes,type,function(i,index,dataFrame,$frame,key,frameData){if(!$frame)return;var fullFLAG=that.fullScreen&&!frameData.$full&&type==="stage";if(frameData.$img&&!again&&!fullFLAG)return;var img=new Image,$img=$(img),imgData=$img.data();frameData[fullFLAG?"$full":"$img"]=$img;var srcKey=type==="stage"?fullFLAG?"full":"img":"thumb",src=dataFrame[srcKey],dummy=fullFLAG?dataFrame["img"]:dataFrame[type==="stage"?"thumb":"img"];if(type==="navThumb")$frame=frameData.$wrap;function triggerTriggerEvent(event){var _index=normalizeIndex(index);triggerEvent(event,{index:_index,src:src,frame:data[_index]})}function error(){$img.remove();$.Fotorama.cache[src]="error";if((!dataFrame.html||type!=="stage")&&dummy&&dummy!==src){dataFrame[srcKey]=src=dummy;frameData.$full=null;loadImg([index],type,specialMeasures,true)}else{if(src&&!dataFrame.html&&!fullFLAG){$frame.trigger("f:error").removeClass(loadingClass).addClass(errorClass);triggerTriggerEvent("error")}else if(type==="stage"){$frame.trigger("f:load").removeClass(loadingClass+" "+errorClass).addClass(loadedClass);triggerTriggerEvent("load");setMeasures()}frameData.state="error";if(size>1&&data[index]===dataFrame&&!dataFrame.html&&!dataFrame.deleted&&!dataFrame.video&&!fullFLAG){dataFrame.deleted=true;that.splice(index,1)}}}function loaded(){$.Fotorama.measures[src]=imgData.measures=$.Fotorama.measures[src]||{width:img.width,height:img.height,ratio:img.width/img.height};setMeasures(imgData.measures.width,imgData.measures.height,imgData.measures.ratio,index);$img.off("load error").addClass(""+(fullFLAG?imgFullClass:imgClass)).attr("aria-hidden","false").prependTo($frame);if($frame.hasClass(stageFrameClass)&&!$frame.hasClass(videoContainerClass)){$frame.attr("href",$img.attr("src"))}fit($img,($.isFunction(specialMeasures)?specialMeasures():specialMeasures)||measures);$.Fotorama.cache[src]=frameData.state="loaded";setTimeout(function(){$frame.trigger("f:load").removeClass(loadingClass+" "+errorClass).addClass(loadedClass+" "+(fullFLAG?loadedFullClass:loadedImgClass));if(type==="stage"){triggerTriggerEvent("load")}else if(dataFrame.thumbratio===AUTO||!dataFrame.thumbratio&&opts.thumbratio===AUTO){dataFrame.thumbratio=imgData.measures.ratio;reset()}},0)}if(!src){error();return}function waitAndLoad(){var _i=10;waitFor(function(){return!touchedFLAG||!_i--&&!SLOW},function(){loaded()})}if(!$.Fotorama.cache[src]){$.Fotorama.cache[src]="*";$img.on("load",waitAndLoad).on("error",error)}else{(function justWait(){if($.Fotorama.cache[src]==="error"){error()}else if($.Fotorama.cache[src]==="loaded"){setTimeout(waitAndLoad,0)}else{setTimeout(justWait,100)}})()}frameData.state="";img.src=src;if(frameData.data.caption){img.alt=frameData.data.caption||""}if(frameData.data.full){$(img).data("original",frameData.data.full)}if(UTIL.isExpectedCaption(dataFrame,opts.showcaption)){$(img).attr("aria-labelledby",dataFrame.labelledby)}})}function updateFotoramaState(){var $frame=activeFrame[STAGE_FRAME_KEY];if($frame&&!$frame.data().state){$spinner.addClass(spinnerShowClass);$frame.on("f:load f:error",function(){$frame.off("f:load f:error");$spinner.removeClass(spinnerShowClass)})}}function addNavFrameEvents(frame){addEnterUp(frame,onNavFrameClick);addFocus(frame,function(){setTimeout(function(){lockScroll($nav)},0);slideNavShaft({time:o_transitionDuration,guessIndex:$(this).data().eq,minMax:navShaftTouchTail})})}function frameDraw(indexes,type){eachIndex(indexes,type,function(i,index,dataFrame,$frame,key,frameData){if($frame)return;$frame=dataFrame[key]=$wrap[key].clone();frameData=$frame.data();frameData.data=dataFrame;var frame=$frame[0],labelledbyValue="labelledby"+$.now();if(type==="stage"){if(dataFrame.html){$('<div class="'+htmlClass+'"></div>').append(dataFrame._html?$(dataFrame.html).removeAttr("id").html(dataFrame._html):dataFrame.html).appendTo($frame)}if(dataFrame.id){labelledbyValue=dataFrame.id||labelledbyValue}dataFrame.labelledby=labelledbyValue;if(UTIL.isExpectedCaption(dataFrame,opts.showcaption)){$($.Fotorama.jst.frameCaption({caption:dataFrame.caption,labelledby:labelledbyValue})).appendTo($frame)}dataFrame.video&&$frame.addClass(stageFrameVideoClass).append($videoPlay.clone());addFocus(frame,function(){setTimeout(function(){lockScroll($stage)},0);clickToShow({index:frameData.eq,user:true})});$stageFrame=$stageFrame.add($frame)}else if(type==="navDot"){addNavFrameEvents(frame);$navDotFrame=$navDotFrame.add($frame)}else if(type==="navThumb"){addNavFrameEvents(frame);frameData.$wrap=$frame.children(":first");$navThumbFrame=$navThumbFrame.add($frame);if(dataFrame.video){frameData.$wrap.append($videoPlay.clone())}}})}function callFit($img,measuresToFit){return $img&&$img.length&&fit($img,measuresToFit)}function stageFramePosition(indexes){eachIndex(indexes,"stage",function(i,index,dataFrame,$frame,key,frameData){if(!$frame)return;var normalizedIndex=normalizeIndex(index);frameData.eq=normalizedIndex;toDetach[STAGE_FRAME_KEY][normalizedIndex]=$frame.css($.extend({left:o_fade?0:getPosByIndex(index,measures.w,opts.margin,repositionIndex)},o_fade&&getDuration(0)));if(isDetached($frame[0])){$frame.appendTo($stageShaft);unloadVideo(dataFrame.$video)}callFit(frameData.$img,measures);callFit(frameData.$full,measures);if($frame.hasClass(stageFrameClass)&&!($frame.attr("aria-hidden")==="false"&&$frame.hasClass(activeClass))){$frame.attr("aria-hidden","true")}})}function thumbsDraw(pos,loadFLAG){var leftLimit,rightLimit,exceedLimit;if(o_nav!=="thumbs"||isNaN(pos))return;leftLimit=-pos;rightLimit=-pos+measures.nw;if(opts.navdir==="vertical"){pos=pos-opts.thumbheight;rightLimit=-pos+measures.h}$navThumbFrame.each(function(){var $this=$(this),thisData=$this.data(),eq=thisData.eq,getSpecialMeasures=function(){return{h:o_thumbSide2,w:thisData.w}},specialMeasures=getSpecialMeasures(),exceedLimit=opts.navdir==="vertical"?thisData.t>rightLimit:thisData.l>rightLimit;specialMeasures.w=thisData.w;if(thisData.l+thisData.w<leftLimit||exceedLimit||callFit(thisData.$img,specialMeasures))return;loadFLAG&&loadImg([eq],"navThumb",getSpecialMeasures)})}function frameAppend($frames,$shaft,type){if(!frameAppend[type]){var thumbsFLAG=type==="nav"&&o_navThumbs,left=0,top=0;$shaft.append($frames.filter(function(){var actual,$this=$(this),frameData=$this.data();for(var _i=0,_l=data.length;_i<_l;_i++){if(frameData.data===data[_i]){actual=true;frameData.eq=_i;break}}return actual||$this.remove()&&false}).sort(function(a,b){return $(a).data().eq-$(b).data().eq}).each(function(){var $this=$(this),frameData=$this.data();UTIL.setThumbAttr($this,frameData.data.caption,"aria-label")}).each(function(){if(!thumbsFLAG)return;var $this=$(this),frameData=$this.data(),thumbwidth=Math.round(o_thumbSide2*frameData.data.thumbratio)||o_thumbSide,thumbheight=Math.round(o_thumbSide/frameData.data.thumbratio)||o_thumbSide2;frameData.t=top;frameData.h=thumbheight;frameData.l=left;frameData.w=thumbwidth;$this.css({width:thumbwidth});top+=thumbheight+opts.thumbmargin;left+=thumbwidth+opts.thumbmargin}));frameAppend[type]=true}}function getDirection(x){return x-stageLeft>measures.w/3}function disableDirrection(i){return!o_loop&&(!(activeIndex+i)||!(activeIndex-size+i))&&!$videoPlaying}function arrsUpdate(){var disablePrev=disableDirrection(0),disableNext=disableDirrection(1);$arrPrev.toggleClass(arrDisabledClass,disablePrev).attr(disableAttr(disablePrev,false));$arrNext.toggleClass(arrDisabledClass,disableNext).attr(disableAttr(disableNext,false))}function thumbArrUpdate(){var isLeftDisable=false,isRightDisable=false;if(opts.navtype==="thumbs"&&!opts.loop){activeIndex==0?isLeftDisable=true:isLeftDisable=false;activeIndex==opts.data.length-1?isRightDisable=true:isRightDisable=false}if(opts.navtype==="slides"){var pos=readPosition($navShaft,opts.navdir);pos>=navShaftTouchTail.max?isLeftDisable=true:isLeftDisable=false;pos<=navShaftTouchTail.min?isRightDisable=true:isRightDisable=false}$thumbArrLeft.toggleClass(arrDisabledClass,isLeftDisable).attr(disableAttr(isLeftDisable,true));$thumbArrRight.toggleClass(arrDisabledClass,isRightDisable).attr(disableAttr(isRightDisable,true))}function stageWheelUpdate(){if(stageWheelTail.ok){stageWheelTail.prevent={"<":disableDirrection(0),">":disableDirrection(1)}}}function getNavFrameBounds($navFrame){var navFrameData=$navFrame.data(),left,top,width,height;if(o_navThumbs){left=navFrameData.l;top=navFrameData.t;width=navFrameData.w;height=navFrameData.h}else{left=$navFrame.position().left;width=$navFrame.width()}var horizontalBounds={c:left+width/2,min:-left+opts.thumbmargin*10,max:-left+measures.w-width-opts.thumbmargin*10};var verticalBounds={c:top+height/2,min:-top+opts.thumbmargin*10,max:-top+measures.h-height-opts.thumbmargin*10};return opts.navdir==="vertical"?verticalBounds:horizontalBounds}function slideThumbBorder(time){var navFrameData=activeFrame[navFrameKey].data();slide($thumbBorder,{time:time*1.2,pos:opts.navdir==="vertical"?navFrameData.t:navFrameData.l,width:navFrameData.w,height:navFrameData.h,direction:opts.navdir})}function slideNavShaft(options){var $guessNavFrame=data[options.guessIndex][navFrameKey],typeOfAnimation=opts.navtype;var overflowFLAG,time,minMax,boundTop,boundLeft,l,pos,x;if($guessNavFrame){if(typeOfAnimation==="thumbs"){overflowFLAG=navShaftTouchTail.min!==navShaftTouchTail.max;minMax=options.minMax||overflowFLAG&&getNavFrameBounds(activeFrame[navFrameKey]);boundTop=overflowFLAG&&(options.keep&&slideNavShaft.t?slideNavShaft.l:minMaxLimit((options.coo||measures.nw/2)-getNavFrameBounds($guessNavFrame).c,minMax.min,minMax.max));boundLeft=overflowFLAG&&(options.keep&&slideNavShaft.l?slideNavShaft.l:minMaxLimit((options.coo||measures.nw/2)-getNavFrameBounds($guessNavFrame).c,minMax.min,minMax.max));l=opts.navdir==="vertical"?boundTop:boundLeft;pos=overflowFLAG&&minMaxLimit(l,navShaftTouchTail.min,navShaftTouchTail.max)||0;time=options.time*1.1;slide($navShaft,{time:time,pos:pos,direction:opts.navdir,onEnd:function(){thumbsDraw(pos,true);thumbArrUpdate()}});setShadow($nav,findShadowEdge(pos,navShaftTouchTail.min,navShaftTouchTail.max,opts.navdir));slideNavShaft.l=l}else{x=readPosition($navShaft,opts.navdir);time=options.time*1.11;pos=validateSlidePos(opts,navShaftTouchTail,options.guessIndex,x,$guessNavFrame,$navWrap,opts.navdir);slide($navShaft,{time:time,pos:pos,direction:opts.navdir,onEnd:function(){thumbsDraw(pos,true);thumbArrUpdate()}});setShadow($nav,findShadowEdge(pos,navShaftTouchTail.min,navShaftTouchTail.max,opts.navdir))}}}function navUpdate(){deactivateFrames(navFrameKey);toDeactivate[navFrameKey].push(activeFrame[navFrameKey].addClass(activeClass).attr("data-active",true))}function deactivateFrames(key){var _toDeactivate=toDeactivate[key];while(_toDeactivate.length){_toDeactivate.shift().removeClass(activeClass).attr("data-active",false)}}function detachFrames(key){var _toDetach=toDetach[key];$.each(activeIndexes,function(i,index){delete _toDetach[normalizeIndex(index)]});$.each(_toDetach,function(index,$frame){delete _toDetach[index];$frame.detach()})}function stageShaftReposition(skipOnEnd){repositionIndex=dirtyIndex=activeIndex;var $frame=activeFrame[STAGE_FRAME_KEY];if($frame){deactivateFrames(STAGE_FRAME_KEY);toDeactivate[STAGE_FRAME_KEY].push($frame.addClass(activeClass).attr("data-active",true));if($frame.hasClass(stageFrameClass)){$frame.attr("aria-hidden","false")}skipOnEnd||that.showStage.onEnd(true);stop($stageShaft,0,true);detachFrames(STAGE_FRAME_KEY);stageFramePosition(activeIndexes);setStageShaftMinmaxAndSnap();setNavShaftMinMax();addEnterUp($stageShaft[0],function(){if(!$fotorama.hasClass(fullscreenClass)){that.requestFullScreen();$fullscreenIcon.focus()}})}}function extendMeasures(options,measuresArray){if(!options)return;$.each(measuresArray,function(i,measures){if(!measures)return;$.extend(measures,{width:options.width||measures.width,height:options.height,minwidth:options.minwidth,maxwidth:options.maxwidth,minheight:options.minheight,maxheight:options.maxheight,ratio:getRatio(options.ratio)})})}function triggerEvent(event,extra){$fotorama.trigger(_fotoramaClass+":"+event,[that,extra])}function onTouchStart(){clearTimeout(onTouchEnd.t);touchedFLAG=1;if(opts.stopautoplayontouch){that.stopAutoplay()}else{pausedAutoplayFLAG=true}}function onTouchEnd(){if(!touchedFLAG)return;if(!opts.stopautoplayontouch){releaseAutoplay();changeAutoplay()}onTouchEnd.t=setTimeout(function(){touchedFLAG=0},TRANSITION_DURATION+TOUCH_TIMEOUT)}function releaseAutoplay(){pausedAutoplayFLAG=!!($videoPlaying||stoppedAutoplayFLAG)}function changeAutoplay(){clearTimeout(changeAutoplay.t);waitFor.stop(changeAutoplay.w);if(!opts.autoplay||pausedAutoplayFLAG){if(that.autoplay){that.autoplay=false;triggerEvent("stopautoplay")}return}if(!that.autoplay){that.autoplay=true;triggerEvent("startautoplay")}var _activeIndex=activeIndex;var frameData=activeFrame[STAGE_FRAME_KEY].data();changeAutoplay.w=waitFor(function(){return frameData.state||_activeIndex!==activeIndex},function(){changeAutoplay.t=setTimeout(function(){if(pausedAutoplayFLAG||_activeIndex!==activeIndex)return;var _nextAutoplayIndex=nextAutoplayIndex,nextFrameData=data[_nextAutoplayIndex][STAGE_FRAME_KEY].data();changeAutoplay.w=waitFor(function(){return nextFrameData.state||_nextAutoplayIndex!==nextAutoplayIndex},function(){if(pausedAutoplayFLAG||_nextAutoplayIndex!==nextAutoplayIndex)return;that.show(o_loop?getDirectionSign(!o_rtl):nextAutoplayIndex)})},opts.autoplay)})}that.startAutoplay=function(interval){if(that.autoplay)return this;pausedAutoplayFLAG=stoppedAutoplayFLAG=false;setAutoplayInterval(interval||opts.autoplay);changeAutoplay();return this};that.stopAutoplay=function(){if(that.autoplay){pausedAutoplayFLAG=stoppedAutoplayFLAG=true;changeAutoplay()}return this};that.showSlide=function(slideDir){var currentPosition=readPosition($navShaft,opts.navdir),pos,time=500*1.1,size=opts.navdir==="horizontal"?opts.thumbwidth:opts.thumbheight,onEnd=function(){thumbArrUpdate()};if(slideDir==="next"){pos=currentPosition-(size+opts.margin)*thumbsPerSlide}if(slideDir==="prev"){pos=currentPosition+(size+opts.margin)*thumbsPerSlide}pos=validateRestrictions(pos,navShaftTouchTail);thumbsDraw(pos,true);slide($navShaft,{time:time,pos:pos,direction:opts.navdir,onEnd:onEnd})};that.showWhileLongPress=function(options){if(that.longPress.singlePressInProgress){return}var index=calcActiveIndex(options);calcGlobalIndexes(index);var time=calcTime(options)/50;var _activeFrame=activeFrame;that.activeFrame=activeFrame=data[activeIndex];var silent=_activeFrame===activeFrame&&!options.user;that.showNav(silent,options,time);return this};that.showEndLongPress=function(options){if(that.longPress.singlePressInProgress){return}var index=calcActiveIndex(options);calcGlobalIndexes(index);var time=calcTime(options)/50;var _activeFrame=activeFrame;that.activeFrame=activeFrame=data[activeIndex];var silent=_activeFrame===activeFrame&&!options.user;that.showStage(silent,options,time);showedFLAG=typeof lastActiveIndex!=="undefined"&&lastActiveIndex!==activeIndex;lastActiveIndex=activeIndex;return this};function calcActiveIndex(options){var index;if(typeof options!=="object"){index=options;options={}}else{index=options.index}index=index===">"?dirtyIndex+1:index==="<"?dirtyIndex-1:index==="<<"?0:index===">>"?size-1:index;index=isNaN(index)?undefined:index;index=typeof index==="undefined"?activeIndex||0:index;return index}function calcGlobalIndexes(index){that.activeIndex=activeIndex=edgeIndex(index);prevIndex=getPrevIndex(activeIndex);nextIndex=getNextIndex(activeIndex);nextAutoplayIndex=normalizeIndex(activeIndex+(o_rtl?-1:1));activeIndexes=[activeIndex,prevIndex,nextIndex];dirtyIndex=o_loop?index:activeIndex}function calcTime(options){var diffIndex=Math.abs(lastActiveIndex-dirtyIndex),time=getNumber(options.time,function(){return Math.min(o_transitionDuration*(1+(diffIndex-1)/12),o_transitionDuration*2)});if(options.slow){time*=10}return time}that.showStage=function(silent,options,time){unloadVideo($videoPlaying,activeFrame.i!==data[normalizeIndex(repositionIndex)].i);frameDraw(activeIndexes,"stage");stageFramePosition(SLOW?[dirtyIndex]:[dirtyIndex,getPrevIndex(dirtyIndex),getNextIndex(dirtyIndex)]);updateTouchTails("go",true);silent||triggerEvent("show",{user:options.user,time:time});pausedAutoplayFLAG=true;var overPos=options.overPos;var onEnd=that.showStage.onEnd=function(skipReposition){if(onEnd.ok)return;onEnd.ok=true;skipReposition||stageShaftReposition(true);if(!silent){triggerEvent("showend",{user:options.user})}if(!skipReposition&&o_transition&&o_transition!==opts.transition){that.setOptions({transition:o_transition});o_transition=false;return}updateFotoramaState();loadImg(activeIndexes,"stage");updateTouchTails("go",false);stageWheelUpdate();stageCursor();releaseAutoplay();changeAutoplay();if(that.fullScreen){activeFrame[STAGE_FRAME_KEY].find("."+imgFullClass).attr("aria-hidden",false);activeFrame[STAGE_FRAME_KEY].find("."+imgClass).attr("aria-hidden",true)}else{activeFrame[STAGE_FRAME_KEY].find("."+imgFullClass).attr("aria-hidden",true);activeFrame[STAGE_FRAME_KEY].find("."+imgClass).attr("aria-hidden",false)}};if(!o_fade){slide($stageShaft,{pos:-getPosByIndex(dirtyIndex,measures.w,opts.margin,repositionIndex),overPos:overPos,time:time,onEnd:onEnd})}else{var $activeFrame=activeFrame[STAGE_FRAME_KEY],$prevActiveFrame=data[lastActiveIndex]&&activeIndex!==lastActiveIndex?data[lastActiveIndex][STAGE_FRAME_KEY]:null;fade($activeFrame,$prevActiveFrame,$stageFrame,{time:time,method:opts.transition,onEnd:onEnd},fadeStack)}arrsUpdate()};that.showNav=function(silent,options,time){thumbArrUpdate();if(o_nav){navUpdate();var guessIndex=limitIndex(activeIndex+minMaxLimit(dirtyIndex-lastActiveIndex,-1,1));slideNavShaft({time:time,coo:guessIndex!==activeIndex&&options.coo,guessIndex:typeof options.coo!=="undefined"?guessIndex:activeIndex,keep:silent});if(o_navThumbs)slideThumbBorder(time)}};that.show=function(options){that.longPress.singlePressInProgress=true;var index=calcActiveIndex(options);calcGlobalIndexes(index);var time=calcTime(options);var _activeFrame=activeFrame;that.activeFrame=activeFrame=data[activeIndex];var silent=_activeFrame===activeFrame&&!options.user;that.showStage(silent,options,time);that.showNav(silent,options,time);showedFLAG=typeof lastActiveIndex!=="undefined"&&lastActiveIndex!==activeIndex;lastActiveIndex=activeIndex;that.longPress.singlePressInProgress=false;return this};that.requestFullScreen=function(){if(o_allowFullScreen&&!that.fullScreen){var isVideo=$((that.activeFrame||{}).$stageFrame||{}).hasClass("fotorama-video-container");if(isVideo){return}scrollTop=$WINDOW.scrollTop();scrollLeft=$WINDOW.scrollLeft();lockScroll($WINDOW);updateTouchTails("x",true);measuresStash=$.extend({},measures);$fotorama.addClass(fullscreenClass).appendTo($BODY.addClass(_fullscreenClass));$HTML.addClass(_fullscreenClass);unloadVideo($videoPlaying,true,true);that.fullScreen=true;if(o_nativeFullScreen){fullScreenApi.request(fotorama)}that.resize();loadImg(activeIndexes,"stage");updateFotoramaState();triggerEvent("fullscreenenter");if(!("ontouchstart"in window)){$fullscreenIcon.focus()}}return this};function cancelFullScreen(){if(that.fullScreen){that.fullScreen=false;if(FULLSCREEN){fullScreenApi.cancel(fotorama)}$BODY.removeClass(_fullscreenClass);$HTML.removeClass(_fullscreenClass);$fotorama.removeClass(fullscreenClass).insertAfter($anchor);measures=$.extend({},measuresStash);unloadVideo($videoPlaying,true,true);updateTouchTails("x",false);that.resize();loadImg(activeIndexes,"stage");lockScroll($WINDOW,scrollLeft,scrollTop);triggerEvent("fullscreenexit")}}that.cancelFullScreen=function(){if(o_nativeFullScreen&&fullScreenApi.is()){fullScreenApi.cancel(document)}else{cancelFullScreen()}return this};that.toggleFullScreen=function(){return that[(that.fullScreen?"cancel":"request")+"FullScreen"]()};that.resize=function(options){if(!data)return this;var time=arguments[1]||0,setFLAG=arguments[2];thumbsPerSlide=getThumbsInSlide($wrap,opts);extendMeasures(!that.fullScreen?optionsToLowerCase(options):{width:$(window).width(),maxwidth:null,minwidth:null,height:$(window).height(),maxheight:null,minheight:null},[measures,setFLAG||that.fullScreen||opts]);var width=measures.width,height=measures.height,ratio=measures.ratio,windowHeight=$WINDOW.height()-(o_nav?$nav.height():0);if(measureIsValid(width)){$wrap.css({width:""});$wrap.css({height:""});$stage.css({width:""});$stage.css({height:""});$stageShaft.css({width:""});$stageShaft.css({height:""});$nav.css({width:""});$nav.css({height:""});$wrap.css({minWidth:measures.minwidth||0,maxWidth:measures.maxwidth||MAX_WIDTH});if(o_nav==="dots"){$navWrap.hide()}width=measures.W=measures.w=$wrap.width();measures.nw=o_nav&&numberFromWhatever(opts.navwidth,width)||width;$stageShaft.css({width:measures.w,marginLeft:(measures.W-measures.w)/2});height=numberFromWhatever(height,windowHeight);height=height||ratio&&width/ratio;if(height){width=Math.round(width);height=measures.h=Math.round(minMaxLimit(height,numberFromWhatever(measures.minheight,windowHeight),numberFromWhatever(measures.maxheight,windowHeight)));$stage.css({width:width,height:height});if(opts.navdir==="vertical"&&!that.fullscreen){$nav.width(opts.thumbwidth+opts.thumbmargin*2)}if(opts.navdir==="horizontal"&&!that.fullscreen){$nav.height(opts.thumbheight+opts.thumbmargin*2)}if(o_nav==="dots"){$nav.width(width).height("auto");$navWrap.show()}if(opts.navdir==="vertical"&&that.fullScreen){$stage.css("height",$WINDOW.height())}if(opts.navdir==="horizontal"&&that.fullScreen){$stage.css("height",$WINDOW.height()-$nav.height())}if(o_nav){switch(opts.navdir){case"vertical":$navWrap.removeClass(navShafthorizontalClass);$navWrap.removeClass(navShaftListClass);$navWrap.addClass(navShaftVerticalClass);$nav.stop().animate({height:measures.h,width:opts.thumbwidth},time);break;case"list":$navWrap.removeClass(navShaftVerticalClass);$navWrap.removeClass(navShafthorizontalClass);$navWrap.addClass(navShaftListClass);break;default:$navWrap.removeClass(navShaftVerticalClass);$navWrap.removeClass(navShaftListClass);$navWrap.addClass(navShafthorizontalClass);$nav.stop().animate({width:measures.nw},time);break}stageShaftReposition();slideNavShaft({guessIndex:activeIndex,time:time,keep:true});if(o_navThumbs&&frameAppend.nav)slideThumbBorder(time)}measuresSetFLAG=setFLAG||true;ready.ok=true;ready()}}stageLeft=$stage.offset().left;setStagePosition();return this};that.setOptions=function(options){$.extend(opts,options);reset();return this};that.shuffle=function(){data&&shuffle(data)&&reset();return this};function setShadow($el,edge){if(o_shadows){$el.removeClass(shadowsLeftClass+" "+shadowsRightClass);$el.removeClass(shadowsTopClass+" "+shadowsBottomClass);edge&&!$videoPlaying&&$el.addClass(edge.replace(/^|\s/g," "+shadowsClass+"--"))}}that.longPress={threshold:1,count:0,thumbSlideTime:20,progress:function(){if(!this.inProgress){this.count++;this.inProgress=this.count>this.threshold}},end:function(){if(this.inProgress){this.isEnded=true}},reset:function(){this.count=0;this.inProgress=false;this.isEnded=false}};that.destroy=function(){that.cancelFullScreen();that.stopAutoplay();data=that.data=null;appendElements();activeIndexes=[];detachFrames(STAGE_FRAME_KEY);reset.ok=false;return this};that.playVideo=function(){var dataFrame=activeFrame,video=dataFrame.video,_activeIndex=activeIndex;if(typeof video==="object"&&dataFrame.videoReady){o_nativeFullScreen&&that.fullScreen&&that.cancelFullScreen();waitFor(function(){return!fullScreenApi.is()||_activeIndex!==activeIndex},function(){if(_activeIndex===activeIndex){dataFrame.$video=dataFrame.$video||$(div(videoClass)).append(createVideoFrame(video));dataFrame.$video.appendTo(dataFrame[STAGE_FRAME_KEY]);$wrap.addClass(wrapVideoClass);$videoPlaying=dataFrame.$video;stageNoMove();$arrs.blur();$fullscreenIcon.blur();triggerEvent("loadvideo")}})}return this};that.stopVideo=function(){unloadVideo($videoPlaying,true,true);return this};that.spliceByIndex=function(index,newImgObj){newImgObj.i=index+1;newImgObj.img&&$.ajax({url:newImgObj.img,type:"HEAD",success:function(){data.splice(index,1,newImgObj);reset()}})};function unloadVideo($video,unloadActiveFLAG,releaseAutoplayFLAG){if(unloadActiveFLAG){$wrap.removeClass(wrapVideoClass);$videoPlaying=false;stageNoMove()}if($video&&$video!==$videoPlaying){$video.remove();triggerEvent("unloadvideo")}if(releaseAutoplayFLAG){releaseAutoplay();changeAutoplay()}}function toggleControlsClass(FLAG){$wrap.toggleClass(wrapNoControlsClass,FLAG)}function stageCursor(e){if(stageShaftTouchTail.flow)return;var x=e?e.pageX:stageCursor.x,pointerFLAG=x&&!disableDirrection(getDirection(x))&&opts.click;if(stageCursor.p!==pointerFLAG&&$stage.toggleClass(pointerClass,pointerFLAG)){stageCursor.p=pointerFLAG;stageCursor.x=x}}$stage.on("mousemove",stageCursor);function clickToShow(showOptions){clearTimeout(clickToShow.t);if(opts.clicktransition&&opts.clicktransition!==opts.transition){setTimeout(function(){var _o_transition=opts.transition;that.setOptions({transition:opts.clicktransition});o_transition=_o_transition;clickToShow.t=setTimeout(function(){that.show(showOptions)},10)},0)}else{that.show(showOptions)}}function onStageTap(e,toggleControlsFLAG){var target=e.target,$target=$(target);if($target.hasClass(videoPlayClass)){that.playVideo()}else if(target===fullscreenIcon){that.toggleFullScreen()}else if($videoPlaying){target===videoClose&&unloadVideo($videoPlaying,true,true)}else if(!$fotorama.hasClass(fullscreenClass)){that.requestFullScreen()}}function updateTouchTails(key,value){stageShaftTouchTail[key]=navShaftTouchTail[key]=value}stageShaftTouchTail=moveOnTouch($stageShaft,{onStart:onTouchStart,onMove:function(e,result){setShadow($stage,result.edge)},onTouchEnd:onTouchEnd,onEnd:function(result){var toggleControlsFLAG;setShadow($stage);toggleControlsFLAG=(MS_POINTER&&!hoverFLAG||result.touch)&&opts.arrows;if((result.moved||toggleControlsFLAG&&result.pos!==result.newPos&&!result.control)&&result.$target[0]!==$fullscreenIcon[0]){var index=getIndexByPos(result.newPos,measures.w,opts.margin,repositionIndex);that.show({index:index,time:o_fade?o_transitionDuration:result.time,overPos:result.overPos,user:true})}else if(!result.aborted&&!result.control){onStageTap(result.startEvent,toggleControlsFLAG)}},timeLow:1,timeHigh:1,friction:2,select:"."+selectClass+", ."+selectClass+" *",$wrap:$stage,direction:"horizontal"});navShaftTouchTail=moveOnTouch($navShaft,{onStart:onTouchStart,onMove:function(e,result){setShadow($nav,result.edge)},onTouchEnd:onTouchEnd,onEnd:function(result){function onEnd(){slideNavShaft.l=result.newPos;releaseAutoplay();changeAutoplay();thumbsDraw(result.newPos,true);thumbArrUpdate()}if(!result.moved){var target=result.$target.closest("."+navFrameClass,$navShaft)[0];target&&onNavFrameClick.call(target,result.startEvent)}else if(result.pos!==result.newPos){pausedAutoplayFLAG=true;slide($navShaft,{time:result.time,pos:result.newPos,overPos:result.overPos,direction:opts.navdir,onEnd:onEnd});thumbsDraw(result.newPos);o_shadows&&setShadow($nav,findShadowEdge(result.newPos,navShaftTouchTail.min,navShaftTouchTail.max,result.dir))}else{onEnd()}},timeLow:.5,timeHigh:2,friction:5,$wrap:$nav,direction:opts.navdir});stageWheelTail=wheel($stage,{shift:true,onEnd:function(e,direction){onTouchStart();onTouchEnd();that.show({index:direction,slow:e.altKey})}});navWheelTail=wheel($nav,{onEnd:function(e,direction){onTouchStart();onTouchEnd();var newPos=stop($navShaft)+direction*.25;$navShaft.css(getTranslate(minMaxLimit(newPos,navShaftTouchTail.min,navShaftTouchTail.max),opts.navdir));o_shadows&&setShadow($nav,findShadowEdge(newPos,navShaftTouchTail.min,navShaftTouchTail.max,opts.navdir));navWheelTail.prevent={"<":newPos>=navShaftTouchTail.max,">":newPos<=navShaftTouchTail.min};clearTimeout(navWheelTail.t);navWheelTail.t=setTimeout(function(){slideNavShaft.l=newPos;thumbsDraw(newPos,true)},TOUCH_TIMEOUT);thumbsDraw(newPos)}});$wrap.hover(function(){setTimeout(function(){if(touchedFLAG)return;toggleControlsClass(!(hoverFLAG=true))},0)},function(){if(!hoverFLAG)return;toggleControlsClass(!(hoverFLAG=false))});function onNavFrameClick(e){var index=$(this).data().eq;if(opts.navtype==="thumbs"){clickToShow({index:index,slow:e.altKey,user:true,coo:e._x-$nav.offset().left})}else{clickToShow({index:index,slow:e.altKey,user:true})}}function onArrClick(e){clickToShow({index:$arrs.index(this)?">":"<",slow:e.altKey,user:true})}smartClick($arrs,function(e){stopEvent(e);onArrClick.call(this,e)},{onStart:function(){onTouchStart();stageShaftTouchTail.control=true},onTouchEnd:onTouchEnd});smartClick($thumbArrLeft,function(e){stopEvent(e);if(opts.navtype==="thumbs"){that.show("<")}else{that.showSlide("prev")}});smartClick($thumbArrRight,function(e){stopEvent(e);if(opts.navtype==="thumbs"){that.show(">")}else{that.showSlide("next")}});function addFocusOnControls(el){addFocus(el,function(){setTimeout(function(){lockScroll($stage)},0);toggleControlsClass(false)})}$arrs.each(function(){addEnterUp(this,function(e){onArrClick.call(this,e)});addFocusOnControls(this)});addEnterUp(fullscreenIcon,function(){if($fotorama.hasClass(fullscreenClass)){that.cancelFullScreen();$stageShaft.focus()}else{that.requestFullScreen();$fullscreenIcon.focus()}});addFocusOnControls(fullscreenIcon);function reset(){setData();setOptions();if(!reset.i){reset.i=true;var _startindex=opts.startindex;activeIndex=repositionIndex=dirtyIndex=lastActiveIndex=startIndex=edgeIndex(_startindex)||0}if(size){if(changeToRtl())return;if($videoPlaying){unloadVideo($videoPlaying,true)}activeIndexes=[];detachFrames(STAGE_FRAME_KEY);reset.ok=true;that.show({index:activeIndex,time:0});that.resize()}else{that.destroy()}}function changeToRtl(){if(!changeToRtl.f===o_rtl){changeToRtl.f=o_rtl;activeIndex=size-1-activeIndex;that.reverse();return true}}$.each("load push pop shift unshift reverse sort splice".split(" "),function(i,method){that[method]=function(){data=data||[];if(method!=="load"){Array.prototype[method].apply(data,arguments)}else if(arguments[0]&&typeof arguments[0]==="object"&&arguments[0].length){data=clone(arguments[0])}reset();return that}});function ready(){if(ready.ok){ready.ok=false;triggerEvent("ready")}}reset()};$.fn.fotorama=function(opts){return this.each(function(){var that=this,$fotorama=$(this),fotoramaData=$fotorama.data(),fotorama=fotoramaData.fotorama;if(!fotorama){waitFor(function(){return!isHidden(that)},function(){fotoramaData.urtext=$fotorama.html();new $.Fotorama($fotorama,$.extend({},OPTIONS,window.fotoramaDefaults,opts,fotoramaData))})}else{fotorama.setOptions(opts,true)}})};$.Fotorama.instances=[];function calculateIndexes(){$.each($.Fotorama.instances,function(index,instance){instance.index=index})}function addInstance(instance){$.Fotorama.instances.push(instance);calculateIndexes()}function hideInstance(instance){$.Fotorama.instances.splice(instance.index,1);calculateIndexes()}$.Fotorama.cache={};$.Fotorama.measures={};$=$||{};$.Fotorama=$.Fotorama||{};$.Fotorama.jst=$.Fotorama.jst||{};$.Fotorama.jst.dots=function(v){var __t,__p="",__e=_.escape;__p+='<div class="fotorama__nav__frame fotorama__nav__frame--dot" tabindex="0" role="button" data-gallery-role="nav-frame" data-nav-type="thumb" aria-label>\r\n <div class="fotorama__dot"></div>\r\n</div>';return __p};$.Fotorama.jst.frameCaption=function(v){var __t,__p="",__e=_.escape;__p+='<div class="fotorama__caption" aria-hidden="true">\r\n <div class="fotorama__caption__wrap" id="'+((__t=v.labelledby)==null?"":__t)+'">'+((__t=v.caption)==null?"":__t)+"</div>\r\n</div>\r\n";return __p};$.Fotorama.jst.style=function(v){var __t,__p="",__e=_.escape;__p+=".fotorama"+((__t=v.s)==null?"":__t)+" .fotorama__nav--thumbs .fotorama__nav__frame{\r\npadding:"+((__t=v.m)==null?"":__t)+"px;\r\nheight:"+((__t=v.h)==null?"":__t)+"px}\r\n.fotorama"+((__t=v.s)==null?"":__t)+" .fotorama__thumb-border{\r\nheight:"+((__t=v.h)==null?"":__t)+"px;\r\nborder-width:"+((__t=v.b)==null?"":__t)+"px;\r\nmargin-top:"+((__t=v.m)==null?"":__t)+"px}";return __p};$.Fotorama.jst.thumb=function(v){var __t,__p="",__e=_.escape;__p+='<div class="fotorama__nav__frame fotorama__nav__frame--thumb" tabindex="0" role="button" data-gallery-role="nav-frame" data-nav-type="thumb" aria-label>\r\n <div class="fotorama__thumb">\r\n </div>\r\n</div>';return __p}})(window,document,location,typeof jQuery!=="undefined"&&jQuery); From 412a51d3ae7dde247c35398908fb2e227a7135de Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Mon, 1 Apr 2019 12:55:16 +0300 Subject: [PATCH 291/603] magento/magento2#21896: Static test fix. --- .../Magento/Contact/view/frontend/web/css/source/_module.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Contact/view/frontend/web/css/source/_module.less b/app/code/Magento/Contact/view/frontend/web/css/source/_module.less index a9454bb6be253..d79806eecbe9b 100644 --- a/app/code/Magento/Contact/view/frontend/web/css/source/_module.less +++ b/app/code/Magento/Contact/view/frontend/web/css/source/_module.less @@ -22,8 +22,8 @@ } // -// Desktop -// _____________________________________________ +// Desktop +// _____________________________________________ .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .contact-index-index .column:not(.sidebar-additional) .form.contact { From 061fa59d8597ebf09e05fff983c663e7fd1161c8 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Mon, 1 Apr 2019 13:05:09 +0300 Subject: [PATCH 292/603] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Changed default value for "UPS type" setting; --- app/code/Magento/Ups/etc/config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ups/etc/config.xml b/app/code/Magento/Ups/etc/config.xml index 791b325c65e3f..73b10dd5ff41b 100644 --- a/app/code/Magento/Ups/etc/config.xml +++ b/app/code/Magento/Ups/etc/config.xml @@ -37,7 +37,7 @@ <negotiated_active>0</negotiated_active> <include_taxes>0</include_taxes> <mode_xml>1</mode_xml> - <type>UPS</type> + <type>UPS_XML</type> <is_account_live>0</is_account_live> <active_rma>0</active_rma> <is_online>1</is_online> From e630b106cc0ae2c609fb2310a2317f35634abc9e Mon Sep 17 00:00:00 2001 From: serhii balko <serhii.balko@transoftgroup.com> Date: Mon, 1 Apr 2019 13:55:43 +0300 Subject: [PATCH 293/603] MAGETWO-98603: [2.3] Fixed Tier Pricing for Bundle items doesn't work --- .../Magento/Bundle/_files/product_with_simple_tier_pricing.php | 2 +- .../Bundle/_files/product_with_simple_tier_pricing_rollback.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php index 30f0978480701..be0f32bdb4cbd 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -require __DIR__ . '/../../../Magento/Catalog/_files/product_simple.php'; +include __DIR__ . '/../../../Magento/Catalog/_files/product_simple.php'; /** @var $productFactory Magento\Catalog\Model\ProductFactory */ $productFactory = $objectManager->create(\Magento\Catalog\Model\ProductFactory::class); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing_rollback.php index aa661c7412d42..6fc56281685aa 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing_rollback.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_rollback.php'; +include __DIR__ . '/../../../Magento/Catalog/_files/product_simple_rollback.php'; /** @var \Magento\Framework\Registry $registry */ $registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class); From 4a70baf3f6d68b0f6a2bee884a1f32a775a93c9a Mon Sep 17 00:00:00 2001 From: serhii balko <serhii.balko@transoftgroup.com> Date: Mon, 1 Apr 2019 15:05:55 +0300 Subject: [PATCH 294/603] MAGETWO-98603: [2.3] Fixed Tier Pricing for Bundle items doesn't work --- .../DataProviders/OptionPriceRendererTest.php | 39 +++++++++++-------- .../product_with_simple_tier_pricing.php | 2 +- ...duct_with_simple_tier_pricing_rollback.php | 2 +- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Bundle/Test/Unit/Block/DataProviders/OptionPriceRendererTest.php b/app/code/Magento/Bundle/Test/Unit/Block/DataProviders/OptionPriceRendererTest.php index 320ed7888e8c6..1af73bafc6256 100644 --- a/app/code/Magento/Bundle/Test/Unit/Block/DataProviders/OptionPriceRendererTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Block/DataProviders/OptionPriceRendererTest.php @@ -51,23 +51,20 @@ protected function setUp() /** * Test to render Tier price html * - * @param bool $priceRenderExist - * @param string $expectedHtml - * @dataProvider renderTierPriceDataProvider + * @return void */ - public function testRenderTierPrice(bool $priceRenderExist, string $expectedHtml): void + public function testRenderTierPrice(): void { - $priceRenderer = false; + $expectedHtml = 'tier price html'; $expectedArguments = ['zone' => Render::ZONE_ITEM_OPTION]; + $productMock = $this->createMock(Product::class); - if ($priceRenderExist) { - $priceRenderer = $this->createPartialMock(BlockInterface::class, ['toHtml', 'render']); - $priceRenderer->expects($this->once()) - ->method('render') - ->with('tier_price', $productMock, $expectedArguments) - ->willReturn($expectedHtml); - } + $priceRenderer = $this->createPartialMock(BlockInterface::class, ['toHtml', 'render']); + $priceRenderer->expects($this->once()) + ->method('render') + ->with('tier_price', $productMock, $expectedArguments) + ->willReturn($expectedHtml); $this->layoutMock->method('getBlock') ->with('product.price.render.default') @@ -81,12 +78,22 @@ public function testRenderTierPrice(bool $priceRenderExist, string $expectedHtml } /** - * Data provider for test to render Tier price + * Test to render Tier price html when render block is not exists * - * @return array + * @return void */ - public function renderTierPriceDataProvider(): array + public function testRenderTierPriceNotExist(): void { - return [[true, 'tier price html'], [false, '']]; + $productMock = $this->createMock(Product::class); + + $this->layoutMock->method('getBlock') + ->with('product.price.render.default') + ->willReturn(false); + + $this->assertEquals( + '', + $this->renderer->renderTierPrice($productMock), + 'Render Tier price is wrong' + ); } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php index be0f32bdb4cbd..30f0978480701 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -include __DIR__ . '/../../../Magento/Catalog/_files/product_simple.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple.php'; /** @var $productFactory Magento\Catalog\Model\ProductFactory */ $productFactory = $objectManager->create(\Magento\Catalog\Model\ProductFactory::class); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing_rollback.php index 6fc56281685aa..aa661c7412d42 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_simple_tier_pricing_rollback.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -include __DIR__ . '/../../../Magento/Catalog/_files/product_simple_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_rollback.php'; /** @var \Magento\Framework\Registry $registry */ $registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class); From 5dd5e3acd8e4d0fc004537effebe6dbd17da5ebb Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Mon, 1 Apr 2019 15:29:04 +0300 Subject: [PATCH 295/603] magento/graphql-ce#540: Replace deprecated Magento/Checkout/_files/quote_with_address_saved.php fixture in SetUpsShippingMethodsOnCartTest --- .../Ups/SetUpsShippingMethodsOnCartTest.php | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index 33f0d4c406020..9ad47319cac1a 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -7,9 +7,9 @@ namespace Magento\GraphQl\Ups; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\Integration\Api\CustomerTokenServiceInterface; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; +use Magento\Quote\Model\Quote; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -30,9 +30,9 @@ class SetUpsShippingMethodsOnCartTest extends GraphQlAbstract const CARRIER_METHOD_CODE_GROUND = 'GND'; /** - * @var QuoteFactory + * @var Quote */ - private $quoteFactory; + private $quote; /** * @var CustomerTokenServiceInterface @@ -40,14 +40,9 @@ class SetUpsShippingMethodsOnCartTest extends GraphQlAbstract private $customerTokenService; /** - * @var QuoteResource + * @var GetMaskedQuoteIdByReservedOrderId */ - private $quoteResource; - - /** - * @var QuoteIdToMaskedQuoteIdInterface - */ - private $quoteIdToMaskedId; + private $getMaskedQuoteIdByReservedOrderId; /** * @inheritdoc @@ -55,15 +50,14 @@ class SetUpsShippingMethodsOnCartTest extends GraphQlAbstract protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); + $this->quote = $objectManager->create(Quote::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/Catalog/_files/products.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -71,9 +65,9 @@ protected function setUp() */ public function testSetUpsShippingMethod() { - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, 'test_quote', 'reserved_order_id'); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); + $quoteReservedId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); + $quote = $this->quote->load($quoteReservedId, 'reserved_order_id'); $shippingAddressId = (int)$quote->getShippingAddress()->getId(); $query = $this->getAddUpsShippingMethodQuery( From 785d826da1bc42683dae3035a5e6c07d7e9813f3 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Mon, 1 Apr 2019 16:09:13 +0300 Subject: [PATCH 296/603] magento/magento2#19987: Static test fix. --- app/code/Magento/Widget/Model/Widget.php | 14 +++++--------- app/code/Magento/Widget/Model/Widget/Config.php | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Widget/Model/Widget.php b/app/code/Magento/Widget/Model/Widget.php index 5cfbfbf9cdf41..af038b8876987 100644 --- a/app/code/Magento/Widget/Model/Widget.php +++ b/app/code/Magento/Widget/Model/Widget.php @@ -248,17 +248,13 @@ public function getWidgets($filters = []) $result = $widgets; // filter widgets by params - if (is_array($filters) && count($filters) > 0) { + if (is_array($filters) && !empty($filters)) { foreach ($widgets as $code => $widget) { - try { - foreach ($filters as $field => $value) { - if (!isset($widget[$field]) || (string)$widget[$field] != $value) { - throw new \Exception(); - } + foreach ($filters as $field => $value) { + if (!isset($widget[$field]) || (string)$widget[$field] != $value) { + unset($result[$code]); + break; } - } catch (\Exception $e) { - unset($result[$code]); - continue; } } } diff --git a/app/code/Magento/Widget/Model/Widget/Config.php b/app/code/Magento/Widget/Model/Widget/Config.php index b259d4e6224be..00b055b35a69d 100644 --- a/app/code/Magento/Widget/Model/Widget/Config.php +++ b/app/code/Magento/Widget/Model/Widget/Config.php @@ -159,7 +159,7 @@ public function getWidgetWindowUrl($config) } } - if (count($skipped) > 0) { + if (!empty($skipped)) { $params['skip_widgets'] = $this->encodeWidgetsToQuery($skipped); } return $this->_backendUrl->getUrl('adminhtml/widget/index', $params); From a7f03dd4f2ec0927e913c753a9b178394b5cd542 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Mon, 1 Apr 2019 16:30:18 +0300 Subject: [PATCH 297/603] magento/magento2#21083: Static test fix. --- .../ConfigurableProduct/Model/LinkManagement.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php b/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php index 06b49d356c5ee..75cab12f63562 100644 --- a/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php +++ b/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -11,6 +10,9 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Exception\StateException; +/** + * Configurable product link management. + */ class LinkManagement implements \Magento\ConfigurableProduct\Api\LinkManagementInterface { /** @@ -68,7 +70,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function getChildren($sku) { @@ -107,7 +109,7 @@ public function getChildren($sku) } /** - * {@inheritdoc} + * @inheritdoc */ public function addChild($sku, $childSku) { @@ -150,7 +152,7 @@ public function addChild($sku, $childSku) } /** - * {@inheritdoc} + * @inheritdoc */ public function removeChild($sku, $childSku) { From 54818de0b2d4a2ef0564babe1c2a2f79ab2e6c23 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Mon, 1 Apr 2019 17:03:46 +0300 Subject: [PATCH 298/603] MAGETWO-64838: Unable to create order from store front if customer address custom attribute is required. - Code refactoring; - Fixed static tests; --- .../Magento/Framework/Webapi/ServiceInputProcessor.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php index f8fe514903ea8..f93d7efda5c8a 100644 --- a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php +++ b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php @@ -146,7 +146,6 @@ private function getNameFinder() * @param string $serviceMethodName name of the method that we are trying to call * @param array $inputArray data to send to method in key-value format * @return array list of parameters that can be used to call the service method - * @throws InputException if no value is provided for required parameters * @throws WebapiException */ public function process($serviceClassName, $serviceMethodName, array $inputArray) @@ -230,6 +229,7 @@ private function getConstructorData(string $className, array $data): array * @param array $data * @return object the newly created and populated object * @throws \Exception + * @throws SerializationException * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function _createFromArray($className, $data) @@ -365,10 +365,10 @@ private function getAttributesPreprocessorsMap(): array /** * Prepare attribute value by loaded attribute preprocessors * - * @param string $key + * @param mixed $key * @param mixed $customAttribute */ - private function runCustomAttributePreprocessors(string $key, &$customAttribute) + private function runCustomAttributePreprocessors($key, &$customAttribute) { $preprocessorsMap = $this->getAttributesPreprocessorsMap(); if ($key && is_array($customAttribute) && array_key_exists($key, $preprocessorsMap)) { @@ -386,6 +386,7 @@ private function runCustomAttributePreprocessors(string $key, &$customAttribute) * * @param string[] $customAttribute * @return string[] + * @throws SerializationException */ private function processCustomAttribute($customAttribute) { From f2f92e6a29ddd9e25305765d3e519443b0984414 Mon Sep 17 00:00:00 2001 From: Ivan Gerchak <ivang@ven.com> Date: Mon, 1 Apr 2019 17:06:08 +0300 Subject: [PATCH 299/603] Add fotorama feature for disabling swipe on the item --- lib/web/fotorama/fotorama.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/web/fotorama/fotorama.js b/lib/web/fotorama/fotorama.js index 093ee707d3f98..b63b9cd872be7 100644 --- a/lib/web/fotorama/fotorama.js +++ b/lib/web/fotorama/fotorama.js @@ -1399,12 +1399,13 @@ fotoramaVersion = '4.6.4'; touchFLAG, targetIsSelectFLAG, targetIsLinkFlag, + isDisabledSwipe, tolerance, moved; function onStart(e) { $target = $(e.target); - tail.checked = targetIsSelectFLAG = targetIsLinkFlag = moved = false; + tail.checked = targetIsSelectFLAG = targetIsLinkFlag = isDisabledSwipe = moved = false; if (touchEnabledFLAG || tail.flow @@ -1415,6 +1416,7 @@ fotoramaVersion = '4.6.4'; touchFLAG = e.type === 'touchstart'; targetIsLinkFlag = $target.is('a, a *', el); + isDisabledSwipe = $target.hasClass('disableSwipe'); controlTouch = tail.control; tolerance = (tail.noMove || tail.noSwipe || controlTouch) ? 16 : !tail.snap ? 4 : 0; @@ -1428,7 +1430,7 @@ fotoramaVersion = '4.6.4'; touchEnabledFLAG = tail.flow = true; - if (!touchFLAG || tail.go) stopEvent(e); + if (!isDisabledSwipe && (!touchFLAG || tail.go)) stopEvent(e); } function onMove(e) { @@ -1441,6 +1443,13 @@ fotoramaVersion = '4.6.4'; return; } + $target = $(e.target); + isDisabledSwipe = $target.hasClass('disableSwipe'); + + if (isDisabledSwipe) { + return; + } + extendEvent(e); var xDiff = Math.abs(e._x - startEvent._x), // opt _x → _pageX From b00402dee226e2a1bc463813b1d3c27b1acbf937 Mon Sep 17 00:00:00 2001 From: Vova Yatsyuk <vova.yatsyuk@gmail.com> Date: Mon, 1 Apr 2019 17:53:05 +0300 Subject: [PATCH 300/603] Fixed assignment of the guest customer to the guest group. This commit fixes the case when guest fills in valid VAT number, then returns to the shipping step and removes VAT from the address. --- .../Observer/Frontend/Quote/Address/CollectTotalsObserver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Quote/Observer/Frontend/Quote/Address/CollectTotalsObserver.php b/app/code/Magento/Quote/Observer/Frontend/Quote/Address/CollectTotalsObserver.php index 76c9a49b290c5..b5e3f4ae1887b 100644 --- a/app/code/Magento/Quote/Observer/Frontend/Quote/Address/CollectTotalsObserver.php +++ b/app/code/Magento/Quote/Observer/Frontend/Quote/Address/CollectTotalsObserver.php @@ -124,7 +124,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) ); } - if ($groupId) { + if ($groupId !== null) { $address->setPrevQuoteCustomerGroupId($quote->getCustomerGroupId()); $quote->setCustomerGroupId($groupId); $this->customerSession->setCustomerGroupId($groupId); From fde1788926782f91da6074aa98f7128f3553c0a6 Mon Sep 17 00:00:00 2001 From: Veronika Kurochkina <veronika_kurochkina@epam.com> Date: Mon, 1 Apr 2019 18:18:49 +0300 Subject: [PATCH 301/603] MAGETWO-65232: Product name does not display special characters properly - Fix static --- .../Model/Order/Pdf/Items/Creditmemo/DefaultCreditmemo.php | 2 ++ .../Sales/Model/Order/Pdf/Items/Invoice/DefaultInvoice.php | 2 ++ .../Sales/Model/Order/Pdf/Items/Shipment/DefaultShipment.php | 2 ++ 3 files changed, 6 insertions(+) diff --git a/app/code/Magento/Sales/Model/Order/Pdf/Items/Creditmemo/DefaultCreditmemo.php b/app/code/Magento/Sales/Model/Order/Pdf/Items/Creditmemo/DefaultCreditmemo.php index 64e569977429c..48934e24a3795 100644 --- a/app/code/Magento/Sales/Model/Order/Pdf/Items/Creditmemo/DefaultCreditmemo.php +++ b/app/code/Magento/Sales/Model/Order/Pdf/Items/Creditmemo/DefaultCreditmemo.php @@ -70,6 +70,7 @@ public function draw() // draw Product name $lines[0] = [ [ + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'text' => $this->string->split(html_entity_decode($item->getName()), 35, true, true), 'feed' => 35 ] @@ -77,6 +78,7 @@ public function draw() // draw SKU $lines[0][] = [ + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'text' => $this->string->split(html_entity_decode($this->getSku($item)), 17), 'feed' => 255, 'align' => 'right', diff --git a/app/code/Magento/Sales/Model/Order/Pdf/Items/Invoice/DefaultInvoice.php b/app/code/Magento/Sales/Model/Order/Pdf/Items/Invoice/DefaultInvoice.php index 4a77053521e4a..23c2c00daadc3 100644 --- a/app/code/Magento/Sales/Model/Order/Pdf/Items/Invoice/DefaultInvoice.php +++ b/app/code/Magento/Sales/Model/Order/Pdf/Items/Invoice/DefaultInvoice.php @@ -70,6 +70,7 @@ public function draw() // draw Product name $lines[0] = [ [ + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'text' => $this->string->split(html_entity_decode($item->getName()), 35, true, true), 'feed' => 35 ] @@ -77,6 +78,7 @@ public function draw() // draw SKU $lines[0][] = [ + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'text' => $this->string->split(html_entity_decode($this->getSku($item)), 17), 'feed' => 290, 'align' => 'right', diff --git a/app/code/Magento/Sales/Model/Order/Pdf/Items/Shipment/DefaultShipment.php b/app/code/Magento/Sales/Model/Order/Pdf/Items/Shipment/DefaultShipment.php index fd18830e45b6e..a88b508ba0789 100644 --- a/app/code/Magento/Sales/Model/Order/Pdf/Items/Shipment/DefaultShipment.php +++ b/app/code/Magento/Sales/Model/Order/Pdf/Items/Shipment/DefaultShipment.php @@ -69,6 +69,7 @@ public function draw() // draw Product name $lines[0] = [ [ + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'text' => $this->string->split(html_entity_decode($item->getName()), 60, true, true), 'feed' => 100 ] @@ -79,6 +80,7 @@ public function draw() // draw SKU $lines[0][] = [ + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'text' => $this->string->split(html_entity_decode($this->getSku($item)), 25), 'feed' => 565, 'align' => 'right', From 74173d39fc5ec350804490cbc6216ad35dc8f16b Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Mon, 1 Apr 2019 10:23:36 -0500 Subject: [PATCH 302/603] Minor fixes for magento/magento-functional-tests-migration#680 - decompose action group - update test annotations --- ...isibleOnCustomerAccountInfoActionGroup.xml | 21 +++++++++ .../CaptchaFormsDisplayingActionGroup.xml | 2 +- ...tomerChangeEmailWithCaptchaActionGroup.xml | 18 +++++++ .../Captcha/Test/Mftf/Data/CaptchaData.xml | 14 ++++++ ...frontCustomerAccountInformationSection.xml | 2 +- ...torefrontCaptchaEditCustomerEmailTest.xml} | 47 +++++++++++-------- ...geCustomerChangeAccountInfoActionGroup.xml | 18 +++++++ ...orefrontCustomerChangeEmailActionGroup.xml | 9 ++-- ...CustomerAccountInfoEditPageActionGroup.xml | 15 ++++++ 9 files changed, 118 insertions(+), 28 deletions(-) create mode 100644 app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerAccountInfoActionGroup.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontCustomerChangeEmailWithCaptchaActionGroup.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/Data/CaptchaData.xml rename app/code/Magento/Captcha/Test/Mftf/Test/{CaptchaEditCustomerTest.xml => StorefrontCaptchaEditCustomerEmailTest.xml} (61%) create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertMessageCustomerChangeAccountInfoActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountInfoEditPageActionGroup.xml diff --git a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerAccountInfoActionGroup.xml b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerAccountInfoActionGroup.xml new file mode 100644 index 0000000000000..ef28705cc7a26 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerAccountInfoActionGroup.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="AssertCaptchaVisibleOnCustomerAccountInfoActionGroup"> + <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaField}}" stepKey="seeCaptchaField"/> + <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaImg}}" stepKey="seeCaptchaImage"/> + <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaReload}}" stepKey="seeCaptchaReloadButton"/> + <reloadPage stepKey="refreshPage"/> + <waitForPageLoad stepKey="waitForPageReloaded" /> + <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaField}}" stepKey="seeCaptchaFieldAfterPageReload"/> + <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaImg}}" stepKey="seeCaptchaImageAfterPageReload"/> + <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaReload}}" stepKey="seeCaptchaReloadButtonAfterPageReload"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/CaptchaFormsDisplayingActionGroup.xml b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/CaptchaFormsDisplayingActionGroup.xml index beb2c2bffa135..f3b6eb1d9af84 100644 --- a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/CaptchaFormsDisplayingActionGroup.xml +++ b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/CaptchaFormsDisplayingActionGroup.xml @@ -7,7 +7,7 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="CaptchaFormsDisplayingActionGroup"> <click selector="{{CaptchaFormsDisplayingSection.store}}" stepKey="ClickToGoStores"/> <waitForPageLoad stepKey="waitForStoresLoaded"/> diff --git a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontCustomerChangeEmailWithCaptchaActionGroup.xml b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontCustomerChangeEmailWithCaptchaActionGroup.xml new file mode 100644 index 0000000000000..8aff3d5482f2c --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontCustomerChangeEmailWithCaptchaActionGroup.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="StorefrontCustomerChangeEmailWithCaptchaActionGroup" extends="StorefrontCustomerChangeEmailActionGroup"> + <arguments> + <argument name="captcha" type="string" /> + </arguments> + + <fillField selector="{{StorefrontCustomerAccountInformationSection.captchaField}}" userInput="{{captcha}}" stepKey="fillCaptchaField" after="fillCurrentPassword" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaData.xml b/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaData.xml new file mode 100644 index 0000000000000..f99bc18f15161 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaData.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="WrongCaptcha"> + <data key="value" unique="suffix">WrongCAPTCHA</data> + </entity> +</entities> diff --git a/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml index 6a274601e69ed..a273c8d4abd28 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml @@ -13,4 +13,4 @@ <element name="captchaImg" type="block" selector=".captcha-img"/> <element name="captchaReload" type="block" selector=".captcha-reload"/> </section> -</sections> \ No newline at end of file +</sections> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaEditCustomerEmailTest.xml similarity index 61% rename from app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml rename to app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaEditCustomerEmailTest.xml index ad126617611c6..9bcc64e9ccaf5 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaEditCustomerEmailTest.xml @@ -8,19 +8,20 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="CaptchaEditCustomerEmailTest"> + <test name="StorefrontCaptchaEditCustomerEmailTest"> <annotations> <features value="Captcha"/> - <stories value="Check captcha and lockout customer on the account edit page."/> - <title value="Test for checking captcha on the customer account edit page and customer is locked."/> + <stories value="Customer Account Info Edit + Captcha"/> + <title value="Test for checking captcha on the customer account edit page."/> <description value="Test for checking captcha on the customer account edit page and customer is locked."/> + <testCaseId value="MC-14013" /> <severity value="MAJOR"/> <group value="captcha"/> <group value="mtf_migrated"/> </annotations> <before> <magentoCLI command="config:set customer/captcha/forms user_edit" stepKey="enableUserEditCaptcha"/> - <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches1"/> + <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> <createData entity="Simple_US_Customer" stepKey="customer"/> <!-- Sign in as customer --> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> @@ -31,17 +32,19 @@ <deleteData createDataKey="customer" stepKey="deleteCustomer"/> <!-- Revert Captcha forms configurations --> <magentoCLI command="config:set customer/captcha/forms user_login,user_forgotpassword" stepKey="revertCaptchaConfigurations"/> - <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches2"/> + <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> </after> <!-- Open Customer edit page --> - <amOnPage url="{{StorefrontCustomerEditPage.url}}" stepKey="goToCustomerEditPage"/> - <waitForPageLoad stepKey="waitForEditPage"/> + <actionGroup ref="StorefrontOpenCustomerAccountInfoEditPageActionGroup" stepKey="goToCustomerEditPage" /> <!-- Update email with incorrect password 3 times. --> <actionGroup ref="StorefrontCustomerChangeEmailActionGroup" stepKey="changeEmailFirstAttempt"> <argument name="email" value="$$customer.email$$" /> <argument name="password" value="{{Colorado_US_Customer.password}}" /> + </actionGroup> + + <actionGroup ref="AssertMessageCustomerChangeAccountInfoActionGroup" stepKey="assertAccountMessageFirstAttempt"> <argument name="message" value="The password doesn't match this account. Verify the password and try again." /> <argument name="messageType" value="error" /> </actionGroup> @@ -49,6 +52,9 @@ <actionGroup ref="StorefrontCustomerChangeEmailActionGroup" stepKey="changeEmailSecondAttempt"> <argument name="email" value="$$customer.email$$" /> <argument name="password" value="{{Colorado_US_Customer.password}}" /> + </actionGroup> + + <actionGroup ref="AssertMessageCustomerChangeAccountInfoActionGroup" stepKey="assertAccountMessageSecondAttempt"> <argument name="message" value="The password doesn't match this account. Verify the password and try again." /> <argument name="messageType" value="error" /> </actionGroup> @@ -56,25 +62,26 @@ <actionGroup ref="StorefrontCustomerChangeEmailActionGroup" stepKey="changeEmailThirdAttempt"> <argument name="email" value="$$customer.email$$" /> <argument name="password" value="{{Colorado_US_Customer.password}}" /> + </actionGroup> + + <actionGroup ref="AssertMessageCustomerChangeAccountInfoActionGroup" stepKey="assertAccountMessageThirdAttempt"> <argument name="message" value="The password doesn't match this account. Verify the password and try again." /> <argument name="messageType" value="error" /> </actionGroup> <!-- Check captcha visibility after incorrect password submit form --> - <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaField}}" stepKey="seeCaptchaField"/> - <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaImg}}" stepKey="seeCaptchaImage"/> - <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaReload}}" stepKey="seeCaptchaReloadButton"/> - <reloadPage stepKey="refreshPage"/> - <waitForPageLoad stepKey="waitForPageReloaded" /> - <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaField}}" stepKey="seeCaptchaFieldAfterPageReload"/> - <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaImg}}" stepKey="seeCaptchaImageAfterPageReload"/> - <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaReload}}" stepKey="seeCaptchaReloadButtonAfterPageReload"/> + <actionGroup ref="AssertCaptchaVisibleOnCustomerAccountInfoActionGroup" stepKey="assertCaptchaVisible" /> <!-- Try to submit form with incorrect captcha --> - <click selector="{{StorefrontCustomerAccountInformationSection.changeEmail}}" stepKey="clickChangeEmailCheckbox4"/> - <fillField selector="{{StorefrontCustomerAccountInformationSection.currentPassword}}" userInput="incorrectPassword" stepKey="enterWrongPassword4"/> - <fillField selector="{{StorefrontCustomerAccountInformationSection.captchaField}}" userInput="wrongCaptcha" stepKey="enterWrongCaptcha"/> - <click selector="{{StorefrontCustomerAccountInformationSection.saveButton}}" stepKey="saveChange4"/> - <see userInput="Incorrect CAPTCHA" selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="verifyMessage4"/> + <actionGroup ref="StorefrontCustomerChangeEmailWithCaptchaActionGroup" stepKey="changeEmailWithIncorrectCaptcha"> + <argument name="email" value="$$customer.email$$" /> + <argument name="password" value="{{Colorado_US_Customer.password}}" /> + <argument name="captcha" value="{{WrongCaptcha.value}}" /> + </actionGroup> + + <actionGroup ref="AssertMessageCustomerChangeAccountInfoActionGroup" stepKey="assertAccountMessageAfterIncorrectCaptcha"> + <argument name="message" value="Incorrect CAPTCHA" /> + <argument name="messageType" value="error" /> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertMessageCustomerChangeAccountInfoActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertMessageCustomerChangeAccountInfoActionGroup.xml new file mode 100644 index 0000000000000..ab48184ed98a8 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertMessageCustomerChangeAccountInfoActionGroup.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="AssertMessageCustomerChangeAccountInfoActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="You saved the account information." /> + <argument name="messageType" type="string" defaultValue="success" /> + </arguments> + <see userInput="{{message}}" selector="{{StorefrontCustomerAccountMainSection.messageByType(messageType)}}" stepKey="verifyMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerChangeEmailActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerChangeEmailActionGroup.xml index 6500d7800b6a1..844d13aa1fe43 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerChangeEmailActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerChangeEmailActionGroup.xml @@ -10,10 +10,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="StorefrontCustomerChangeEmailActionGroup"> <arguments> - <argument name="email" type="string" /> - <argument name="password" type="string" /> - <argument name="message" type="string" defaultValue="You saved the account information." /> - <argument name="messageType" type="string" defaultValue="success" /> + <argument name="email" type="string" /> + <argument name="password" type="string" /> </arguments> <conditionalClick selector="{{StorefrontCustomerSidebarSection.sidebarTab('Account Information')}}" dependentSelector="{{StorefrontCustomerSidebarSection.sidebarTab('Account Information')}}" visible="true" stepKey="openAccountInfoTab" /> <waitForPageLoad stepKey="waitForAccountInfoTabOpened" /> @@ -22,6 +20,5 @@ <fillField selector="{{StorefrontCustomerAccountInformationSection.currentPassword}}" userInput="{{password}}" stepKey="fillCurrentPassword" /> <click selector="{{StorefrontCustomerAccountInformationSection.saveButton}}" stepKey="saveChange" /> <waitForPageLoad stepKey="waitForPageLoaded" /> - <see userInput="{{message}}" selector="{{StorefrontCustomerAccountMainSection.messageByType(messageType)}}" stepKey="verifyMessage" /> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountInfoEditPageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountInfoEditPageActionGroup.xml new file mode 100644 index 0000000000000..c1ea2da8a9519 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountInfoEditPageActionGroup.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="StorefrontOpenCustomerAccountInfoEditPageActionGroup"> + <amOnPage url="{{StorefrontCustomerEditPage.url}}" stepKey="goToCustomerEditPage"/> + <waitForPageLoad stepKey="waitForEditPage"/> + </actionGroup> +</actionGroups> From bb7be7ada6f64686116df9fbb79bcb64b226bb7a Mon Sep 17 00:00:00 2001 From: Dmytro Cheshun <mitry@atwix.com> Date: Mon, 1 Apr 2019 20:33:17 +0300 Subject: [PATCH 303/603] Add API functional tests for ApplyCouponToCart functionality --- .../Magento/GraphQl/Quote/CouponTest.php | 85 ---- .../Quote/Customer/ApplyCouponToCartTest.php | 416 ++++++++++++++++++ .../Quote/Guest/ApplyCouponToCartTest.php | 337 ++++++++++++++ 3 files changed, 753 insertions(+), 85 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/CouponTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/CouponTest.php index 828784ca27885..31c03754e048c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/CouponTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/CouponTest.php @@ -41,91 +41,6 @@ protected function setUp() $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); } - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php - */ - public function testApplyCouponToGuestCartWithItems() - { - $couponCode = '2?ds5!2d'; - - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $response = $this->graphQlQuery($query); - - self::assertArrayHasKey('applyCouponToCart', $response); - self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php - */ - public function testApplyCouponTwice() - { - $couponCode = '2?ds5!2d'; - - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $response = $this->graphQlQuery($query); - - self::assertArrayHasKey("applyCouponToCart", $response); - self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); - - self::expectExceptionMessage('A coupon is already applied to the cart. Please remove it to apply another'); - $this->graphQlQuery($query); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php - * @expectedException \Exception - * @expectedExceptionMessage Cart does not contain products. - */ - public function testApplyCouponToCartWithNoItems() - { - $couponCode = '2?ds5!2d'; - - $this->quoteResource->load($this->quote, 'test_order_1', 'reserved_order_id'); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - - $this->graphQlQuery($query); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php - * @magentoApiDataFixture Magento/Customer/_files/customer.php - */ - public function testGuestCustomerAttemptToChangeCustomerCart() - { - $couponCode = '2?ds5!2d'; - - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - - self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query); - } - /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php new file mode 100644 index 0000000000000..0a1b7036ef977 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php @@ -0,0 +1,416 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\Framework\Exception\AuthenticationException; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\SalesRule\Model\Coupon; +use Magento\SalesRule\Model\Rule; +use Magento\SalesRule\Model\Spi\CouponResourceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test Apply Coupon to Cart functionality for customer + */ +class ApplyCouponToCartTest extends GraphQlAbstract +{ + /** + * @var QuoteResource + */ + private $quoteResource; + + /** + * @var Quote + */ + private $quote; + + /** + * @var QuoteIdToMaskedQuoteIdInterface + */ + private $quoteIdToMaskedId; + + /** + * @var CouponResourceInterface + */ + protected $couponResource; + + /** + * @var Coupon + */ + private $coupon; + + /** + * @var Rule + */ + private $salesRule; + + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->quoteResource = $objectManager->create(QuoteResource::class); + $this->quote = $objectManager->create(Quote::class); + $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); + $this->couponResource = $objectManager->get(CouponResourceInterface::class); + $this->coupon = $objectManager->create(Coupon::class); + $this->salesRule = $objectManager->create(Rule::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + */ + public function testApplyCouponToCart() + { + $couponCode = '2?ds5!2d'; + + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $this->quote->setCustomerId(1); + $this->quoteResource->save($this->quote); + $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $response = $this->graphQlQuery($query, [], '', $queryHeaders); + + self::assertArrayHasKey('applyCouponToCart', $response); + self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @expectedException \Exception + * @expectedExceptionMessage A coupon is already applied to the cart. Please remove it to apply another + */ + public function testApplyCouponTwice() + { + $couponCode = '2?ds5!2d'; + + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $this->quote->setCustomerId(1); + $this->quoteResource->save($this->quote); + $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $response = $this->graphQlQuery($query, [], '', $queryHeaders); + + self::assertArrayHasKey("applyCouponToCart", $response); + self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); + + $this->graphQlQuery($query, [], '', $queryHeaders); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @expectedException \Exception + * @expectedExceptionMessage Cart does not contain products. + */ + public function testApplyCouponToCartWithoutItems() + { + $couponCode = '2?ds5!2d'; + + $this->quoteResource->load($this->quote, 'test_order_1', 'reserved_order_id'); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $this->quote->setCustomerId(1); + $this->quoteResource->save($this->quote); + $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + + $this->graphQlQuery($query, [], '', $queryHeaders); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @expectedException \Exception + */ + public function testApplyCouponToGuestCart() + { + $couponCode = '2?ds5!2d'; + + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + + self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); + $this->graphQlQuery($query, [], '', $queryHeaders); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/two_customers.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @expectedException \Exception + */ + public function testApplyCouponToAnotherCustomerCart() + { + $couponCode = '2?ds5!2d'; + + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $this->quote->setCustomerId(2); + $this->quoteResource->save($this->quote); + $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + + self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); + $this->graphQlQuery($query, [], '', $queryHeaders); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @expectedException \Exception + * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. + */ + public function testApplyNonExistentCouponToCart() + { + $couponCode = '1%q#f5'; + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $this->quote->setCustomerId(1); + $this->quoteResource->save($this->quote); + $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + + $this->graphQlQuery($query, [], '', $queryHeaders); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @expectedException \Exception + */ + public function testApplyCouponToNonExistentCart() + { + $couponCode = '2?ds5!2d'; + $maskedQuoteId = '1hk3y1842h1n'; + $this->quote->setCustomerId(1); + $this->quoteResource->save($this->quote); + $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + + self::expectExceptionMessage('Could not find a cart with ID "' . $maskedQuoteId . '"'); + $this->graphQlQuery($query, [], '', $queryHeaders); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @expectedException \Exception + * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. + */ + public function testApplyExpiredCoupon() + { + $couponCode = '2?ds5!2d'; + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $this->quote->setCustomerId(1); + $this->quoteResource->save($this->quote); + $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + + $this->coupon->loadByCode($couponCode); + $yesterday = new \DateTime(); + $yesterday->add(\DateInterval::createFromDateString('-1 day')); + $this->coupon->setExpirationDate($yesterday->format('Y-m-d')); + $this->couponResource->save($this->coupon); + + $this->graphQlQuery($query, [], '', $queryHeaders); + } + + /** + * Products in cart don't fit to the coupon + * + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @expectedException \Exception + * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. + */ + public function testApplyCouponWhichIsNotApplicable() + { + $couponCode = '2?ds5!2d'; + + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $this->quote->setCustomerId(1); + $this->quoteResource->save($this->quote); + $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $this->excludeProductPerCoupon($couponCode, 'simple'); + + $this->graphQlQuery($query, [], '', $queryHeaders); + } + + /** + * @param string $input + * @param string $message + * @dataProvider dataProviderUpdateWithMissedRequiredParameters + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @expectedException \Exception + */ + public function testApplyCouponWithMissedRequiredParameters(string $input, string $message) + { + $query = <<<QUERY +mutation { + applyCouponToCart(input: {{$input}}) { + cart { + applied_coupon { + code + } + } + } +} +QUERY; + + $this->quote->setCustomerId(1); + $this->quoteResource->save($this->quote); + $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); + + $this->expectExceptionMessage($message); + $this->graphQlQuery($query, [], '', $queryHeaders); + } + + /** + * @return array + */ + public function dataProviderUpdateWithMissedRequiredParameters(): array + { + return [ + 'missed_cart_id' => [ + 'coupon_code: "test"', + 'Required parameter "cart_id" is missing' + ], + 'missed_coupon_code' => [ + 'cart_id: "test"', + 'Required parameter "coupon_code" is missing' + ], + ]; + } + + /** + * @param string $couponCode + * @param string $sku + * @throws \Exception + */ + private function excludeProductPerCoupon(string $couponCode, string $sku) + { + $this->coupon->loadByCode($couponCode); + $ruleId = $this->coupon->getRuleId(); + $salesRule = $this->salesRule->load($ruleId); + $salesRule->getConditions()->loadArray([ + 'type' => \Magento\SalesRule\Model\Rule\Condition\Combine::class, + 'attribute' => null, + 'operator' => null, + 'value' => '1', + 'is_value_processed' => null, + 'aggregator' => 'all', + 'conditions' => + [ + [ + 'type' => \Magento\SalesRule\Model\Rule\Condition\Product\Found::class, + 'attribute' => null, + 'operator' => null, + 'value' => '1', + 'is_value_processed' => null, + 'aggregator' => 'all', + 'conditions' => + [ + [ + 'type' => \Magento\SalesRule\Model\Rule\Condition\Product::class, + 'attribute' => 'sku', + 'operator' => '!=', + 'value' => $sku, + 'is_value_processed' => false, + ], + ], + ], + ], + ]); + $this->salesRule->save(); + } + + /** + * Retrieve customer authorization headers + * + * @param string $email + * @param string $password + * @return array + * @throws AuthenticationException + */ + private function prepareAuthorizationHeaders(string $email, string $password): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($email, $password); + return ['Authorization' => 'Bearer ' . $customerToken]; + } + + /** + * @param string $maskedQuoteId + * @param string $couponCode + * @return string + */ + private function prepareAddCouponRequestQuery(string $maskedQuoteId, string $couponCode): string + { + return <<<QUERY +mutation { + applyCouponToCart(input: {cart_id: "$maskedQuoteId", coupon_code: "$couponCode"}) { + cart { + applied_coupon { + code + } + } + } +} +QUERY; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php new file mode 100644 index 0000000000000..5c70fb9637dba --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php @@ -0,0 +1,337 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\SalesRule\Model\Coupon; +use Magento\SalesRule\Model\Rule; +use Magento\SalesRule\Model\Spi\CouponResourceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test Apply Coupon to Cart functionality for guest + */ +class ApplyCouponToCartTest extends GraphQlAbstract +{ + /** + * @var QuoteResource + */ + private $quoteResource; + + /** + * @var Quote + */ + private $quote; + + /** + * @var QuoteIdToMaskedQuoteIdInterface + */ + private $quoteIdToMaskedId; + + /** + * @var CouponResourceInterface + */ + protected $couponResource; + + /** + * @var Coupon + */ + private $coupon; + + /** + * @var Rule + */ + private $salesRule; + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->quoteResource = $objectManager->create(QuoteResource::class); + $this->quote = $objectManager->create(Quote::class); + $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); + $this->couponResource = $objectManager->get(CouponResourceInterface::class); + $this->coupon = $objectManager->create(Coupon::class); + $this->salesRule = $objectManager->create(Rule::class); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + */ + public function testApplyCouponToCart() + { + $couponCode = '2?ds5!2d'; + + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $response = $this->graphQlQuery($query); + + self::assertArrayHasKey('applyCouponToCart', $response); + self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @expectedException \Exception + * @expectedExceptionMessage A coupon is already applied to the cart. Please remove it to apply another + */ + public function testApplyCouponTwice() + { + $couponCode = '2?ds5!2d'; + + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $response = $this->graphQlQuery($query); + + self::assertArrayHasKey("applyCouponToCart", $response); + self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); + + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @expectedException \Exception + * @expectedExceptionMessage Cart does not contain products. + */ + public function testApplyCouponToCartWithoutItems() + { + $couponCode = '2?ds5!2d'; + + $this->quoteResource->load($this->quote, 'test_order_1', 'reserved_order_id'); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @expectedException \Exception + */ + public function testApplyCouponToCustomerCart() + { + $couponCode = '2?ds5!2d'; + + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $this->quote->setCustomerId(1); + $this->quoteResource->save($this->quote); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + + self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @expectedException \Exception + * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. + */ + public function testApplyNonExistentCouponToCart() + { + $couponCode = '1%q#f5'; + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @expectedException \Exception + */ + public function testApplyCouponToNonExistentCart() + { + $couponCode = '2?ds5!2d'; + $maskedQuoteId = '1hk3y1842h1n'; + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + + self::expectExceptionMessage('Could not find a cart with ID "' . $maskedQuoteId . '"'); + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @expectedException \Exception + * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. + */ + public function testApplyExpiredCoupon() + { + $couponCode = '2?ds5!2d'; + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $this->coupon->loadByCode($couponCode); + + $yesterday = new \DateTime(); + $yesterday->add(\DateInterval::createFromDateString('-1 day')); + $this->coupon->setExpirationDate($yesterday->format('Y-m-d')); + $this->couponResource->save($this->coupon); + + $this->graphQlQuery($query); + } + + /** + * Products in cart don't fit to the coupon + * + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @expectedException \Exception + * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. + */ + public function testApplyCouponWhichIsNotApplicable() + { + $couponCode = '2?ds5!2d'; + + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $this->excludeProductPerCoupon($couponCode, 'simple'); + + $this->graphQlQuery($query); + } + + /** + * @param string $input + * @param string $message + * @dataProvider dataProviderUpdateWithMissedRequiredParameters + * @expectedException \Exception + */ + public function testApplyCouponWithMissedRequiredParameters(string $input, string $message) + { + $query = <<<QUERY +mutation { + applyCouponToCart(input: {{$input}}) { + cart { + applied_coupon { + code + } + } + } +} +QUERY; + + $this->expectExceptionMessage($message); + $this->graphQlQuery($query); + } + + /** + * @return array + */ + public function dataProviderUpdateWithMissedRequiredParameters(): array + { + return [ + 'missed_cart_id' => [ + 'coupon_code: "test"', + 'Required parameter "cart_id" is missing' + ], + 'missed_coupon_code' => [ + 'cart_id: "test"', + 'Required parameter "coupon_code" is missing' + ], + ]; + } + + /** + * @param string $couponCode + * @param string $sku + * @throws \Exception + */ + private function excludeProductPerCoupon(string $couponCode, string $sku) + { + $this->coupon->loadByCode($couponCode); + $ruleId = $this->coupon->getRuleId(); + $salesRule = $this->salesRule->load($ruleId); + $salesRule->getConditions()->loadArray([ + 'type' => \Magento\SalesRule\Model\Rule\Condition\Combine::class, + 'attribute' => null, + 'operator' => null, + 'value' => '1', + 'is_value_processed' => null, + 'aggregator' => 'all', + 'conditions' => + [ + [ + 'type' => \Magento\SalesRule\Model\Rule\Condition\Product\Found::class, + 'attribute' => null, + 'operator' => null, + 'value' => '1', + 'is_value_processed' => null, + 'aggregator' => 'all', + 'conditions' => + [ + [ + 'type' => \Magento\SalesRule\Model\Rule\Condition\Product::class, + 'attribute' => 'sku', + 'operator' => '!=', + 'value' => $sku, + 'is_value_processed' => false, + ], + ], + ], + ], + ]); + $this->salesRule->save(); + } + + /** + * @param string $maskedQuoteId + * @param string $couponCode + * @return string + */ + private function prepareAddCouponRequestQuery(string $maskedQuoteId, string $couponCode): string + { + return <<<QUERY +mutation { + applyCouponToCart(input: {cart_id: "$maskedQuoteId", coupon_code: "$couponCode"}) { + cart { + applied_coupon { + code + } + } + } +} +QUERY; + } +} From 149dec143aa5f884056537e79aea9ce53848cd62 Mon Sep 17 00:00:00 2001 From: Dmytro Cheshun <mitry@atwix.com> Date: Mon, 1 Apr 2019 21:00:27 +0300 Subject: [PATCH 304/603] Code refactoring --- .../Quote/Customer/ApplyCouponToCartTest.php | 77 ++++++++++--------- .../Quote/Guest/ApplyCouponToCartTest.php | 73 +++++++++--------- 2 files changed, 78 insertions(+), 72 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php index 0a1b7036ef977..2db2e799f9123 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php @@ -12,8 +12,10 @@ use Magento\Quote\Model\Quote; use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\SalesRule\Api\Data\ConditionInterface; +use Magento\SalesRule\Api\Data\ConditionInterfaceFactory; +use Magento\SalesRule\Api\RuleRepositoryInterface; use Magento\SalesRule\Model\Coupon; -use Magento\SalesRule\Model\Rule; use Magento\SalesRule\Model\Spi\CouponResourceInterface; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -49,14 +51,19 @@ class ApplyCouponToCartTest extends GraphQlAbstract private $coupon; /** - * @var Rule + * @var CustomerTokenServiceInterface */ - private $salesRule; + private $customerTokenService; /** - * @var CustomerTokenServiceInterface + * @var RuleRepositoryInterface */ - private $customerTokenService; + private $ruleRepository; + + /** + * @var ConditionInterfaceFactory + */ + private $conditionFactory; protected function setUp() { @@ -66,8 +73,9 @@ protected function setUp() $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); $this->couponResource = $objectManager->get(CouponResourceInterface::class); $this->coupon = $objectManager->create(Coupon::class); - $this->salesRule = $objectManager->create(Rule::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->ruleRepository = $objectManager->get(RuleRepositoryInterface::class); + $this->conditionFactory = $objectManager->get(ConditionInterfaceFactory::class); } /** @@ -347,37 +355,32 @@ private function excludeProductPerCoupon(string $couponCode, string $sku) { $this->coupon->loadByCode($couponCode); $ruleId = $this->coupon->getRuleId(); - $salesRule = $this->salesRule->load($ruleId); - $salesRule->getConditions()->loadArray([ - 'type' => \Magento\SalesRule\Model\Rule\Condition\Combine::class, - 'attribute' => null, - 'operator' => null, - 'value' => '1', - 'is_value_processed' => null, - 'aggregator' => 'all', - 'conditions' => - [ - [ - 'type' => \Magento\SalesRule\Model\Rule\Condition\Product\Found::class, - 'attribute' => null, - 'operator' => null, - 'value' => '1', - 'is_value_processed' => null, - 'aggregator' => 'all', - 'conditions' => - [ - [ - 'type' => \Magento\SalesRule\Model\Rule\Condition\Product::class, - 'attribute' => 'sku', - 'operator' => '!=', - 'value' => $sku, - 'is_value_processed' => false, - ], - ], - ], - ], - ]); - $this->salesRule->save(); + $salesRule = $this->ruleRepository->getById($ruleId); + + /** @var ConditionInterface $conditionProductSku */ + $conditionProductSku = $this->conditionFactory->create(); + $conditionProductSku->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Product::class); + $conditionProductSku->setAttributeName('sku'); + $conditionProductSku->setValue('1'); + $conditionProductSku->setOperator('!='); + $conditionProductSku->setValue($sku); + + /** @var ConditionInterface $conditionProductFound */ + $conditionProductFound = $this->conditionFactory->create(); + $conditionProductFound->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Product\Found::class); + $conditionProductFound->setValue('1'); + $conditionProductFound->setAggregatorType('all'); + $conditionProductFound->setConditions([$conditionProductSku]); + + /** @var ConditionInterface $conditionCombine */ + $conditionCombine = $this->conditionFactory->create(); + $conditionCombine->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Combine::class); + $conditionCombine->setValue('1'); + $conditionCombine->setAggregatorType('all'); + $conditionCombine->setConditions([$conditionProductFound]); + + $salesRule->setCondition($conditionCombine); + $this->ruleRepository->save($salesRule); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php index 5c70fb9637dba..51644a9fe8c55 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php @@ -10,8 +10,10 @@ use Magento\Quote\Model\Quote; use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\SalesRule\Api\Data\ConditionInterface; +use Magento\SalesRule\Api\Data\ConditionInterfaceFactory; +use Magento\SalesRule\Api\RuleRepositoryInterface; use Magento\SalesRule\Model\Coupon; -use Magento\SalesRule\Model\Rule; use Magento\SalesRule\Model\Spi\CouponResourceInterface; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -47,9 +49,14 @@ class ApplyCouponToCartTest extends GraphQlAbstract private $coupon; /** - * @var Rule + * @var RuleRepositoryInterface */ - private $salesRule; + private $ruleRepository; + + /** + * @var ConditionInterfaceFactory + */ + private $conditionFactory; protected function setUp() { @@ -59,7 +66,8 @@ protected function setUp() $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); $this->couponResource = $objectManager->get(CouponResourceInterface::class); $this->coupon = $objectManager->create(Coupon::class); - $this->salesRule = $objectManager->create(Rule::class); + $this->ruleRepository = $objectManager->get(RuleRepositoryInterface::class); + $this->conditionFactory = $objectManager->get(ConditionInterfaceFactory::class); } /** @@ -282,37 +290,32 @@ private function excludeProductPerCoupon(string $couponCode, string $sku) { $this->coupon->loadByCode($couponCode); $ruleId = $this->coupon->getRuleId(); - $salesRule = $this->salesRule->load($ruleId); - $salesRule->getConditions()->loadArray([ - 'type' => \Magento\SalesRule\Model\Rule\Condition\Combine::class, - 'attribute' => null, - 'operator' => null, - 'value' => '1', - 'is_value_processed' => null, - 'aggregator' => 'all', - 'conditions' => - [ - [ - 'type' => \Magento\SalesRule\Model\Rule\Condition\Product\Found::class, - 'attribute' => null, - 'operator' => null, - 'value' => '1', - 'is_value_processed' => null, - 'aggregator' => 'all', - 'conditions' => - [ - [ - 'type' => \Magento\SalesRule\Model\Rule\Condition\Product::class, - 'attribute' => 'sku', - 'operator' => '!=', - 'value' => $sku, - 'is_value_processed' => false, - ], - ], - ], - ], - ]); - $this->salesRule->save(); + $salesRule = $this->ruleRepository->getById($ruleId); + + /** @var ConditionInterface $conditionProductSku */ + $conditionProductSku = $this->conditionFactory->create(); + $conditionProductSku->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Product::class); + $conditionProductSku->setAttributeName('sku'); + $conditionProductSku->setValue('1'); + $conditionProductSku->setOperator('!='); + $conditionProductSku->setValue($sku); + + /** @var ConditionInterface $conditionProductFound */ + $conditionProductFound = $this->conditionFactory->create(); + $conditionProductFound->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Product\Found::class); + $conditionProductFound->setValue('1'); + $conditionProductFound->setAggregatorType('all'); + $conditionProductFound->setConditions([$conditionProductSku]); + + /** @var ConditionInterface $conditionCombine */ + $conditionCombine = $this->conditionFactory->create(); + $conditionCombine->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Combine::class); + $conditionCombine->setValue('1'); + $conditionCombine->setAggregatorType('all'); + $conditionCombine->setConditions([$conditionProductFound]); + + $salesRule->setCondition($conditionCombine); + $this->ruleRepository->save($salesRule); } /** From ead2ab834ff52e43e797644a4297ea8b335a24ee Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Mon, 1 Apr 2019 23:18:30 +0300 Subject: [PATCH 305/603] Refactoring --- ... => StorefrontContactUsCaptchaSection.xml} | 2 +- .../Test/Mftf/Test/CaptchaOnContactUsTest.xml | 31 +++++++++---------- .../Mftf/Page/StorefrontContactUsPage.xml | 15 +++++++++ .../StorefrontContactUsFormSection.xml | 17 ++++++++++ .../Test/TestCase/CaptchaOnContactUsTest.xml | 1 + 5 files changed, 49 insertions(+), 17 deletions(-) rename app/code/Magento/Captcha/Test/Mftf/Section/{StorefrontContactUsFormSection.xml => StorefrontContactUsCaptchaSection.xml} (94%) create mode 100644 app/code/Magento/Contact/Test/Mftf/Page/StorefrontContactUsPage.xml create mode 100644 app/code/Magento/Contact/Test/Mftf/Section/StorefrontContactUsFormSection.xml diff --git a/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsFormSection.xml b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsCaptchaSection.xml similarity index 94% rename from app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsFormSection.xml rename to app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsCaptchaSection.xml index 235712b0b5b57..ef7a419194628 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsFormSection.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsCaptchaSection.xml @@ -8,7 +8,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> - <section name="StorefrontContactUsFormSection"> + <section name="StorefrontContactUsCaptchaSection"> <element name="captchaField" type="input" selector="#captcha_contact_us"/> <element name="captchaImg" type="block" selector=".captcha-img"/> <element name="captchaReload" type="block" selector=".captcha-reload"/> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnContactUsTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnContactUsTest.xml index 64978f32aa61a..cd839b0f78400 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnContactUsTest.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnContactUsTest.xml @@ -20,35 +20,34 @@ </annotations> <before> <magentoCLI command="config:set customer/captcha/forms contact_us" stepKey="enableUserEditCaptcha"/> - <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches1"/> - <createData entity="Simple_US_Customer" stepKey="customer"/> + <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> </before> <after> <magentoCLI command="config:set customer/captcha/forms user_login,user_forgotpassword" stepKey="revertCaptchaConfigurations"/> - <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches2"/> - <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> </after> <!-- Open storefront contact us form --> - <amOnPage url="/contact/" stepKey="amOnContactUpPage"/> - <waitForPageLoad stepKey="waitForContactUpPage"/> + <amOnPage url="{{StorefrontContactUsPage.url}}" stepKey="amOnContactUpPage"/> + <waitForPageLoad stepKey="waitForContactUpPageLoad"/> <!-- Check Captcha items --> - <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaField}}" stepKey="seeCaptchaField1"/> - <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaImg}}" stepKey="seeCaptchaImage1"/> - <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaReload}}" stepKey="seeCaptchaReloadButton1"/> + <waitForElementVisible selector="{{StorefrontContactUsCaptchaSection.captchaField}}" stepKey="seeCaptchaFieldFirst"/> + <waitForElementVisible selector="{{StorefrontContactUsCaptchaSection.captchaImg}}" stepKey="seeCaptchaImageFirst"/> + <waitForElementVisible selector="{{StorefrontContactUsCaptchaSection.captchaReload}}" stepKey="seeCaptchaReloadButtonFirst"/> <!-- Submit Contact Us form --> - <fillField selector="{{StorefrontContactUsFormSection.emailField}}" userInput="$$customer.email$$" stepKey="fillEmail"/> - <fillField selector="{{StorefrontContactUsFormSection.nameField}}" userInput="$$customer.firstname$$" stepKey="fillName"/> - <fillField selector="{{StorefrontContactUsFormSection.commentField}}" userInput="Lorem ipsum dolor sit amet, ne enim aliquando eam, oblique deserunt no usu." stepKey="fillComment"/> - <fillField selector="{{StorefrontContactUsFormSection.captchaField}}" userInput="InvalidCaptcha" stepKey="fillCaptcha" /> + <fillField selector="{{StorefrontContactUsFormSection.emailField}}" userInput="{{Simple_US_Customer.email}}" stepKey="fillEmail"/> + <fillField selector="{{StorefrontContactUsFormSection.nameField}}" userInput="{{Simple_US_Customer.firstname}}" stepKey="fillName"/> + <fillField selector="{{StorefrontContactUsFormSection.commentField}}" userInput="Lorem ipsum dolor sit amet, ne enim aliquando eam, oblique deserunt no usu." + stepKey="fillComment"/> + <fillField selector="{{StorefrontContactUsCaptchaSection.captchaField}}" userInput="InvalidCaptcha" stepKey="fillCaptcha" /> <click selector="{{StorefrontContactUsFormSection.submitFormButton}}" stepKey="clickSubmitFormButton"/> <!-- Check Captcha items after form reload --> <see userInput="Incorrect CAPTCHA" selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="verifyMessage"/> - <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaField}}" stepKey="seeCaptchaField2"/> - <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaImg}}" stepKey="seeCaptchaImage2"/> - <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaReload}}" stepKey="seeCaptchaReloadButton2"/> + <waitForElementVisible selector="{{StorefrontContactUsCaptchaSection.captchaField}}" stepKey="seeCaptchaFieldSecond"/> + <waitForElementVisible selector="{{StorefrontContactUsCaptchaSection.captchaImg}}" stepKey="seeCaptchaImageSecond"/> + <waitForElementVisible selector="{{StorefrontContactUsCaptchaSection.captchaReload}}" stepKey="seeCaptchaReloadButtonSecond"/> </test> </tests> diff --git a/app/code/Magento/Contact/Test/Mftf/Page/StorefrontContactUsPage.xml b/app/code/Magento/Contact/Test/Mftf/Page/StorefrontContactUsPage.xml new file mode 100644 index 0000000000000..b8d1de812d887 --- /dev/null +++ b/app/code/Magento/Contact/Test/Mftf/Page/StorefrontContactUsPage.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="StorefrontContactUsPage" url="/contact/" area="storefront" module="Magento_Contact"> + <section name="StorefrontContactUsFormSection"/> + <section name="StorefrontContactUsCaptchaSection"/> + </page> +</pages> diff --git a/app/code/Magento/Contact/Test/Mftf/Section/StorefrontContactUsFormSection.xml b/app/code/Magento/Contact/Test/Mftf/Section/StorefrontContactUsFormSection.xml new file mode 100644 index 0000000000000..a73d1ad1297ef --- /dev/null +++ b/app/code/Magento/Contact/Test/Mftf/Section/StorefrontContactUsFormSection.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontContactUsFormSection"> + <element name="nameField" type="input" selector="#name"/> + <element name="emailField" type="input" selector="#email"/> + <element name="commentField" type="textarea" selector="#comment"/> + <element name="submitFormButton" type="button" selector=".action.submit.primary" timeout="30"/> + </section> +</sections> diff --git a/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnContactUsTest.xml b/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnContactUsTest.xml index a88cd98e3c31b..1a25afeabc5de 100644 --- a/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnContactUsTest.xml +++ b/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnContactUsTest.xml @@ -12,6 +12,7 @@ <data name="comment/data/captcha" xsi:type="string">111</data> <data name="comment/data/customer/dataset" xsi:type="string">default</data> <data name="configData" xsi:type="string">captcha_storefront_contact_us</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Contact\Test\Constraint\AssertContactUsSuccessMessage" /> </variation> </testCase> From 116e11f00e2fde53a6e9c4c3ce92a4458316d135 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Mon, 1 Apr 2019 23:20:56 +0300 Subject: [PATCH 306/603] Refactoring --- .../Test/Mftf/Section/StorefrontContactUsCaptchaSection.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsCaptchaSection.xml b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsCaptchaSection.xml index ef7a419194628..f587812576ff1 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsCaptchaSection.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsCaptchaSection.xml @@ -12,9 +12,5 @@ <element name="captchaField" type="input" selector="#captcha_contact_us"/> <element name="captchaImg" type="block" selector=".captcha-img"/> <element name="captchaReload" type="block" selector=".captcha-reload"/> - <element name="nameField" type="input" selector="#name"/> - <element name="emailField" type="input" selector="#email"/> - <element name="commentField" type="textarea" selector="#comment"/> - <element name="submitFormButton" type="button" selector=".action.submit.primary" timeout="30"/> </section> </sections> From c380fa0e9b9255e0f1d821e41e67f1fe4dde0da1 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Mon, 1 Apr 2019 15:35:51 -0500 Subject: [PATCH 307/603] MC-15439: Deferred loading / parsing of JS --- app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php index 7bc02164e7a85..19ef31b2a41b4 100644 --- a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php @@ -22,7 +22,7 @@ public function beforeSendResponse(\Magento\Framework\App\Response\Http $subject $script = []; if (strpos($content, '</body') > 0) { $content = preg_replace('#<!--(?!\s?/?ko).*?-->#s', '', $content); - $pattern = '#<script.*?</script>#is'; + $pattern = '#<script[^>]*+(?<!text/x-magento-template.)>.*?</script>#is'; $content = preg_replace_callback( $pattern, function ($matchPart) use (&$script) { From 0d5fce3b3ae89385d9d41b6cf20e64f0bfe5fb41 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Mon, 1 Apr 2019 15:52:17 -0500 Subject: [PATCH 308/603] Minor fixes for magento/magento-functional-tests-migration#681 - update test annotations - provided additional verification of CAPTCHA --- ...OnCustomerAccountCreatePageActionGroup.xml | 16 ++++ ...ountCreationFormWithCaptchaActionGroup.xml | 17 ++++ .../Test/Mftf/Data/CaptchaConfigData.xml | 93 +++++++++++++++++++ .../Captcha/Test/Mftf/Data/CaptchaData.xml | 11 ++- .../Mftf/Data/CaptchaFormsDisplayingData.xml | 2 +- .../StorefrontCustomerCreateFormSection.xml | 16 ++++ .../Test/CaptchaOnStoreFrontRegisterTest.xml | 51 ---------- ...StorefrontCaptchaEditCustomerEmailTest.xml | 23 ++++- ...orefrontCaptchaRegisterNewCustomerTest.xml | 68 ++++++++++++++ ...essageCustomerCreateAccountActionGroup.xml | 18 ++++ ...CustomerAccountCreationFormActionGroup.xml | 15 +++ ...CustomerAccountCreationFormActionGroup.xml | 22 +++++ ...enCustomerAccountCreatePageActionGroup.xml | 15 +++ .../StorefrontCustomerCreateFormSection.xml | 3 - .../CaptchaOnStoreFrontRegisterTest.xml | 1 + 15 files changed, 309 insertions(+), 62 deletions(-) create mode 100644 app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerAccountCreatePageActionGroup.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontFillCustomerAccountCreationFormWithCaptchaActionGroup.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml delete mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontRegisterTest.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaRegisterNewCustomerTest.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertMessageCustomerCreateAccountActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontClickCreateAnAccountCustomerAccountCreationFormActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillCustomerAccountCreationFormActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountCreatePageActionGroup.xml diff --git a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerAccountCreatePageActionGroup.xml b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerAccountCreatePageActionGroup.xml new file mode 100644 index 0000000000000..6c09d1d49381f --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerAccountCreatePageActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertCaptchaVisibleOnCustomerAccountCreatePageActionGroup"> + <waitForElementVisible selector="{{StorefrontCustomerCreateFormSection.captchaField}}" stepKey="waitForCaptchaField"/> + <waitForElementVisible selector="{{StorefrontCustomerCreateFormSection.captchaImg}}" stepKey="waitForCaptchaImage"/> + <waitForElementVisible selector="{{StorefrontCustomerCreateFormSection.captchaReload}}" stepKey="waitForCaptchaReloadButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontFillCustomerAccountCreationFormWithCaptchaActionGroup.xml b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontFillCustomerAccountCreationFormWithCaptchaActionGroup.xml new file mode 100644 index 0000000000000..d67ebc1a00768 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontFillCustomerAccountCreationFormWithCaptchaActionGroup.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="StorefrontFillCustomerAccountCreationFormWithCaptchaActionGroup" extends="StorefrontFillCustomerAccountCreationFormActionGroup"> + <arguments> + <argument name="captcha" type="string" /> + </arguments> + <fillField stepKey="fillCaptchaField" after="fillConfirmPassword" userInput="{{captcha}}" selector="{{StorefrontCustomerCreateFormSection.captchaField}}" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml b/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml new file mode 100644 index 0000000000000..12bbb5b55dab0 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml @@ -0,0 +1,93 @@ +<?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="StorefrontCustomerCaptchaEnableConfigData"> + <!-- Magento default value --> + <data key="path">customer/captcha/enable</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="StorefrontCustomerCaptchaDisableConfigData"> + <data key="path">customer/captcha/enable</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="StorefrontCaptchaOnCustomerCreateFormConfigData"> + <data key="path">customer/captcha/forms</data> + <data key="scope_id">0</data> + <data key="label">Create user</data> + <data key="value">user_create</data> + </entity> + <entity name="StorefrontCaptchaOnCustomerLoginConfigData"> + <!-- Magento default value --> + <data key="path">customer/captcha/forms</data> + <data key="scope_id">0</data> + <data key="label">Login</data> + <data key="value">user_login</data> + </entity> + <entity name="StorefrontCaptchaOnCustomerChangePasswordConfigData"> + <data key="path">customer/captcha/forms</data> + <data key="scope_id">0</data> + <data key="label">Change password</data> + <data key="value">user_edit</data> + </entity> + <entity name="StorefrontCaptchaOnCustomerForgotPasswordConfigData"> + <!-- Magento default value --> + <data key="path">customer/captcha/forms</data> + <data key="scope_id">0</data> + <data key="label">Forgot password</data> + <data key="value">user_forgotpassword</data> + </entity> + <entity name="StorefrontCustomerCaptchaModeAlwaysConfigData"> + <data key="path">customer/captcha/mode</data> + <data key="scope_id">0</data> + <data key="label">Always</data> + <data key="value">always</data> + </entity> + <entity name="StorefrontCustomerCaptchaModeAfterFailConfigData"> + <!-- Magento default value --> + <data key="path">customer/captcha/mode</data> + <data key="scope_id">0</data> + <data key="label">After number of attempts to login</data> + <data key="value">after_fail</data> + </entity> + <entity name="StorefrontCustomerCaptchaLength3ConfigData"> + <data key="path">customer/captcha/length</data> + <data key="scope">admin</data> + <data key="scope_id">1</data> + <data key="label">3</data> + <data key="value">3</data> + </entity> + <entity name="StorefrontCustomerCaptchaSymbols1ConfigData"> + <data key="path">customer/captcha/symbols</data> + <data key="scope">admin</data> + <data key="scope_id">1</data> + <data key="label">1</data> + <data key="value">1</data> + </entity> + <entity name="StorefrontCustomerCaptchaDefaultLengthConfigData"> + <!-- Magento default value --> + <data key="path">customer/captcha/length</data> + <data key="scope">admin</data> + <data key="scope_id">1</data> + <data key="label">4-5</data> + <data key="value">4-5</data> + </entity> + <entity name="StorefrontCustomerCaptchaDefaultSymbolsConfigData"> + <!-- Magento default value --> + <data key="path">customer/captcha/symbols</data> + <data key="scope">admin</data> + <data key="scope_id">1</data> + <data key="label">ABCDEFGHJKMnpqrstuvwxyz23456789</data> + <data key="value">ABCDEFGHJKMnpqrstuvwxyz23456789</data> + </entity> +</entities> diff --git a/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaData.xml b/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaData.xml index f99bc18f15161..d8fb206b8111c 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaData.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaData.xml @@ -7,8 +7,13 @@ --> <entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd"> - <entity name="WrongCaptcha"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="WrongCaptcha"> <data key="value" unique="suffix">WrongCAPTCHA</data> - </entity> + </entity> + + <!-- This CAPTCHA will only work if "StorefrontCustomerCaptchaLength3ConfigData" and "StorefrontCustomerCaptchaSymbols1ConfigData" config is set. --> + <entity name="PreconfiguredCaptcha"> + <data key="value">111</data> + </entity> </entities> diff --git a/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaFormsDisplayingData.xml b/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaFormsDisplayingData.xml index 9db8110c0f64b..57a09219fe4db 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaFormsDisplayingData.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaFormsDisplayingData.xml @@ -7,7 +7,7 @@ --> <entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> <entity name="CaptchaData"> <data key="createUser">Create user</data> <data key="login">Login</data> diff --git a/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml new file mode 100644 index 0000000000000..f48e6124cb214 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontCustomerCreateFormSection"> + <element name="captchaField" type="input" selector="#captcha_user_create"/> + <element name="captchaImg" type="block" selector=".captcha-img"/> + <element name="captchaReload" type="block" selector=".captcha-reload"/> + </section> +</sections> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontRegisterTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontRegisterTest.xml deleted file mode 100644 index 86a660563086e..0000000000000 --- a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontRegisterTest.xml +++ /dev/null @@ -1,51 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="CaptchaOnStoreFrontRegisterTest"> - <annotations> - <features value="Captcha"/> - <stories value="Test creation for customer register with captcha on storefront."/> - <title value="Captcha customer registration"/> - <description value="Test creation for customer register with captcha on storefront."/> - <severity value="MAJOR"/> - <group value="captcha"/> - <group value="mtf_migrated"/> - </annotations> - <before> - <!-- Enable captcha for customer. --> - <magentoCLI command="config:set customer/captcha/forms user_create" stepKey="enableUserRegistrationCaptcha"/> - <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches1"/> - </before> - <after> - <!-- Set default configuration. --> - <magentoCLI command="config:set customer/captcha/forms user_login,user_forgotpassword" stepKey="revertCaptchaConfigurations"/> - <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches2"/> - </after> - - <!-- Open Customer registration page --> - <amOnPage url="/customer/account/create/" stepKey="goToRegistrationPage"/> - <waitForPageLoad stepKey="waitForRegistrationPage"/> - - <!-- Check captcha visibility registration page load --> - <waitForElementVisible selector="{{StorefrontCustomerCreateFormSection.captchaField}}" stepKey="seeCaptchaField"/> - <waitForElementVisible selector="{{StorefrontCustomerCreateFormSection.captchaImg}}" stepKey="seeCaptchaImage"/> - <waitForElementVisible selector="{{StorefrontCustomerCreateFormSection.captchaReload}}" stepKey="seeCaptchaReloadButton"/> - - <!-- Submit form with incorrect captcha --> - <fillField selector="{{StorefrontCustomerCreateFormSection.firstnameField}}" userInput="FirstName" stepKey="fillFirstName"/> - <fillField selector="{{StorefrontCustomerCreateFormSection.lastnameField}}" userInput="LastName" stepKey="fillLastName" /> - <fillField stepKey="fillEmail" userInput="email@example.com" selector="{{StorefrontCustomerCreateFormSection.emailField}}"/> - <fillField stepKey="fillPassword" userInput="123123Qq" selector="{{StorefrontCustomerCreateFormSection.passwordField}}"/> - <fillField stepKey="fillConfirmPassword" userInput="123123Qq" selector="{{StorefrontCustomerCreateFormSection.confirmPasswordField}}"/> - <fillField selector="{{StorefrontCustomerCreateFormSection.captchaField}}" userInput="wrongCaptcha" stepKey="enterWrongCaptcha"/> - <click stepKey="clickCreateAccountButton" selector="{{StorefrontCustomerCreateFormSection.createAccountButton}}"/> - <see userInput="Incorrect CAPTCHA" selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="verifyMessage4"/> - </test> -</tests> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaEditCustomerEmailTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaEditCustomerEmailTest.xml index 9bcc64e9ccaf5..99ce58bc3d174 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaEditCustomerEmailTest.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaEditCustomerEmailTest.xml @@ -15,13 +15,17 @@ <title value="Test for checking captcha on the customer account edit page."/> <description value="Test for checking captcha on the customer account edit page and customer is locked."/> <testCaseId value="MC-14013" /> - <severity value="MAJOR"/> + <severity value="AVERAGE"/> <group value="captcha"/> <group value="mtf_migrated"/> </annotations> <before> - <magentoCLI command="config:set customer/captcha/forms user_edit" stepKey="enableUserEditCaptcha"/> + <!-- Setup CAPTCHA for testing --> + <magentoCLI command="config:set {{StorefrontCaptchaOnCustomerChangePasswordConfigData.path}} {{StorefrontCaptchaOnCustomerChangePasswordConfigData.value}}" stepKey="enableUserEditCaptcha"/> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaLength3ConfigData.path}} {{StorefrontCustomerCaptchaLength3ConfigData.value}}" stepKey="setCaptchaLength" /> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaSymbols1ConfigData.path}} {{StorefrontCustomerCaptchaSymbols1ConfigData.value}}" stepKey="setCaptchaSymbols" /> <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> + <createData entity="Simple_US_Customer" stepKey="customer"/> <!-- Sign in as customer --> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> @@ -29,10 +33,13 @@ </actionGroup> </before> <after> - <deleteData createDataKey="customer" stepKey="deleteCustomer"/> <!-- Revert Captcha forms configurations --> - <magentoCLI command="config:set customer/captcha/forms user_login,user_forgotpassword" stepKey="revertCaptchaConfigurations"/> + <magentoCLI command="config:set {{StorefrontCaptchaOnCustomerLoginConfigData.path}} {{StorefrontCaptchaOnCustomerLoginConfigData.value}},{{StorefrontCaptchaOnCustomerForgotPasswordConfigData.value}}" stepKey="enableCaptchaOnDefaultForms" /> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaDefaultLengthConfigData.path}} {{StorefrontCustomerCaptchaDefaultLengthConfigData.value}}" stepKey="setDefaultCaptchaLength" /> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaDefaultSymbolsConfigData.path}} {{StorefrontCustomerCaptchaDefaultSymbolsConfigData.value}}" stepKey="setDefaultCaptchaSymbols" /> <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> + + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> <!-- Open Customer edit page --> @@ -83,5 +90,13 @@ <argument name="message" value="Incorrect CAPTCHA" /> <argument name="messageType" value="error" /> </actionGroup> + + <!-- Update customer email correct password and CAPTCHA --> + <actionGroup ref="StorefrontCustomerChangeEmailWithCaptchaActionGroup" stepKey="changeEmailCorrectAttempt"> + <argument name="email" value="$$customer.email$$" /> + <argument name="password" value="$$customer.password$$" /> + <argument name="captcha" value="{{PreconfiguredCaptcha.value}}" /> + </actionGroup> + <actionGroup ref="AssertMessageCustomerChangeAccountInfoActionGroup" stepKey="assertAccountMessageCorrectAttempt" /> </test> </tests> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaRegisterNewCustomerTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaRegisterNewCustomerTest.xml new file mode 100644 index 0000000000000..cce8a1570682b --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaRegisterNewCustomerTest.xml @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCaptchaRegisterNewCustomerTest"> + <annotations> + <features value="Captcha"/> + <stories value="Create New Customer Account + Captcha"/> + <title value="Test creation for customer register with captcha on storefront."/> + <description value="Test creation for customer register with captcha on storefront."/> + <severity value="AVERAGE"/> + <testCaseId value="MC-14805" /> + <group value="captcha"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Enable captcha for customer. --> + <magentoCLI command="config:set {{StorefrontCaptchaOnCustomerCreateFormConfigData.path}} {{StorefrontCaptchaOnCustomerCreateFormConfigData.value}}" stepKey="enableUserRegistrationCaptcha" /> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaModeAlwaysConfigData.path}} {{StorefrontCustomerCaptchaModeAlwaysConfigData.value}}" stepKey="alwaysEnableCaptcha" /> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaLength3ConfigData.path}} {{StorefrontCustomerCaptchaLength3ConfigData.value}}" stepKey="setCaptchaLength" /> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaSymbols1ConfigData.path}} {{StorefrontCustomerCaptchaSymbols1ConfigData.value}}" stepKey="setCaptchaSymbols" /> + <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> + </before> + <after> + <!-- Set default configuration. --> + <magentoCLI command="config:set {{StorefrontCaptchaOnCustomerLoginConfigData.path}} {{StorefrontCaptchaOnCustomerLoginConfigData.value}},{{StorefrontCaptchaOnCustomerForgotPasswordConfigData.value}}" stepKey="enableCaptchaOnDefaultForms" /> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaModeAfterFailConfigData.path}} {{StorefrontCustomerCaptchaModeAfterFailConfigData.value}}" stepKey="defaultCaptchaMode" /> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaDefaultLengthConfigData.path}} {{StorefrontCustomerCaptchaDefaultLengthConfigData.value}}" stepKey="setDefaultCaptchaLength" /> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaDefaultSymbolsConfigData.path}} {{StorefrontCustomerCaptchaDefaultSymbolsConfigData.value}}" stepKey="setDefaultCaptchaSymbols" /> + <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> + </after> + + <!-- Open Customer registration page --> + <actionGroup ref="StorefrontOpenCustomerAccountCreatePageActionGroup" stepKey="goToCustomerAccountCreatePage" /> + + <!-- Check captcha visibility registration page load --> + <actionGroup ref="AssertCaptchaVisibleOnCustomerAccountCreatePageActionGroup" stepKey="verifyCaptchaVisible" /> + + <!-- Submit form with incorrect captcha --> + <actionGroup ref="StorefrontFillCustomerAccountCreationFormWithCaptchaActionGroup" stepKey="fillNewCustomerAccountFormWithIncorrectCaptcha"> + <argument name="customer" value="Simple_US_Customer" /> + <argument name="captcha" value="{{WrongCaptcha.value}}" /> + </actionGroup> + + <actionGroup ref="StorefrontClickCreateAnAccountCustomerAccountCreationFormActionGroup" stepKey="clickCreateAnAccountButton" /> + + <actionGroup ref="AssertMessageCustomerCreateAccountActionGroup" stepKey="assertMessage"> + <argument name="message" value="Incorrect CAPTCHA" /> + <argument name="messageType" value="error" /> + </actionGroup> + + <actionGroup ref="AssertCaptchaVisibleOnCustomerAccountCreatePageActionGroup" stepKey="verifyCaptchaVisibleAfterFail" /> + + <!-- Submit form with correct captcha --> + <actionGroup ref="StorefrontFillCustomerAccountCreationFormWithCaptchaActionGroup" stepKey="fillNewCustomerAccountFormWithCorrectCaptcha"> + <argument name="customer" value="Simple_US_Customer" /> + <argument name="captcha" value="{{PreconfiguredCaptcha.value}}" /> + </actionGroup> + <actionGroup ref="StorefrontClickCreateAnAccountCustomerAccountCreationFormActionGroup" stepKey="clickCreateAnAccountButtonAfterCorrectCaptcha" /> + <actionGroup ref="AssertMessageCustomerCreateAccountActionGroup" stepKey="assertSuccessMessage" /> + </test> +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertMessageCustomerCreateAccountActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertMessageCustomerCreateAccountActionGroup.xml new file mode 100644 index 0000000000000..65c9b025a9c2d --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertMessageCustomerCreateAccountActionGroup.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="AssertMessageCustomerCreateAccountActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="Thank you for registering with Main Website Store." /> + <argument name="messageType" type="string" defaultValue="success" /> + </arguments> + <see userInput="{{message}}" selector="{{StorefrontCustomerAccountMainSection.messageByType(messageType)}}" stepKey="verifyMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontClickCreateAnAccountCustomerAccountCreationFormActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontClickCreateAnAccountCustomerAccountCreationFormActionGroup.xml new file mode 100644 index 0000000000000..dfb9d1b2c259a --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontClickCreateAnAccountCustomerAccountCreationFormActionGroup.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="StorefrontClickCreateAnAccountCustomerAccountCreationFormActionGroup"> + <click stepKey="clickCreateAccountButton" selector="{{StorefrontCustomerCreateFormSection.createAccountButton}}" /> + <waitForPageLoad stepKey="waitForCustomerSaved" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillCustomerAccountCreationFormActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillCustomerAccountCreationFormActionGroup.xml new file mode 100644 index 0000000000000..62d77d4548cce --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillCustomerAccountCreationFormActionGroup.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="StorefrontFillCustomerAccountCreationFormActionGroup"> + <arguments> + <argument name="customer" type="entity" /> + </arguments> + + <fillField stepKey="fillFirstName" userInput="{{customer.firstname}}" selector="{{StorefrontCustomerCreateFormSection.firstnameField}}" /> + <fillField stepKey="fillLastName" userInput="{{customer.lastname}}" selector="{{StorefrontCustomerCreateFormSection.lastnameField}}" /> + <fillField stepKey="fillEmail" userInput="{{customer.email}}" selector="{{StorefrontCustomerCreateFormSection.emailField}}"/> + <fillField stepKey="fillPassword" userInput="{{customer.password}}" selector="{{StorefrontCustomerCreateFormSection.passwordField}}"/> + <fillField stepKey="fillConfirmPassword" userInput="{{customer.password}}" selector="{{StorefrontCustomerCreateFormSection.confirmPasswordField}}"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountCreatePageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountCreatePageActionGroup.xml new file mode 100644 index 0000000000000..0ae470d0497ab --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountCreatePageActionGroup.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="StorefrontOpenCustomerAccountCreatePageActionGroup"> + <amOnPage url="{{StorefrontCustomerCreatePage.url}}" stepKey="goToCustomerAccountCreatePage"/> + <waitForPageLoad stepKey="waitForPageLoaded"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml index 68851e88ec4b2..8881a2a012ce8 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml @@ -17,9 +17,6 @@ <element name="passwordField" type="input" selector="#password"/> <element name="confirmPasswordField" type="input" selector="#password-confirmation"/> <element name="createAccountButton" type="button" selector="button.action.submit.primary" timeout="30"/> - <element name="captchaField" type="input" selector="#captcha_user_create"/> - <element name="captchaImg" type="block" selector=".captcha-img"/> - <element name="captchaReload" type="block" selector=".captcha-reload"/> </section> <section name="StoreFrontCustomerAdvancedAttributesSection"> <element name="textFieldAttribute" type="input" selector="//input[@id='{{var}}']" parameterized="true" /> diff --git a/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnStoreFrontRegisterTest.xml b/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnStoreFrontRegisterTest.xml index 8e83c189efc2f..b0ce6dfa561ae 100644 --- a/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnStoreFrontRegisterTest.xml +++ b/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnStoreFrontRegisterTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Captcha\Test\TestCase\CaptchaOnStoreFrontRegisterTest" summary="Check CAPTCHA on StoreFront Register Page" ticketId="MAGETWO-43602"> <variation name="CaptchaOnStoreFrontRegisterTestVariation1"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="customer/dataset" xsi:type="string">register_customer</data> <data name="customer/data/captcha" xsi:type="string">111</data> <data name="configData" xsi:type="string">captcha_storefront_register</data> From ba6c5239689f5b7cfc09f03042284742b00499e7 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Tue, 2 Apr 2019 01:52:56 +0300 Subject: [PATCH 309/603] magento/graphql-ce#540: Replace deprecated Magento/Checkout/_files/quote_with_address_saved.php fixture in SetUpsShippingMethodsOnCartTest --- .../Ups/SetUpsShippingMethodsOnCartTest.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index 9ad47319cac1a..32e9cbf990523 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -8,8 +8,8 @@ namespace Magento\GraphQl\Ups; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\GraphQl\Quote\GetQuoteShippingAddressIdByReservedQuoteId; use Magento\Integration\Api\CustomerTokenServiceInterface; -use Magento\Quote\Model\Quote; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -30,9 +30,9 @@ class SetUpsShippingMethodsOnCartTest extends GraphQlAbstract const CARRIER_METHOD_CODE_GROUND = 'GND'; /** - * @var Quote + * @var GetQuoteShippingAddressIdByReservedQuoteId */ - private $quote; + private $getQuoteShippingAddressIdByReservedQuoteId; /** * @var CustomerTokenServiceInterface @@ -50,9 +50,9 @@ class SetUpsShippingMethodsOnCartTest extends GraphQlAbstract protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quote = $objectManager->create(Quote::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->getQuoteShippingAddressIdByReservedQuoteId = $objectManager->get(GetQuoteShippingAddressIdByReservedQuoteId::class); } /** @@ -67,10 +67,9 @@ public function testSetUpsShippingMethod() { $quoteReservedId = 'test_quote'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); - $quote = $this->quote->load($quoteReservedId, 'reserved_order_id'); - $shippingAddressId = (int)$quote->getShippingAddress()->getId(); + $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - $query = $this->getAddUpsShippingMethodQuery( + $query = $this->getQuery( $maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, @@ -96,7 +95,7 @@ public function testSetUpsShippingMethod() * @param string $methodCode * @return string */ - private function getAddUpsShippingMethodQuery( + private function getQuery( string $maskedQuoteId, int $shippingAddressId, string $carrierCode, From 41d6d26e72b106ac9809cfe98cf6ecdc8bfdf793 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Tue, 2 Apr 2019 02:03:27 +0300 Subject: [PATCH 310/603] magento/graphql-ce#559: Fix misspelling in GetQuoteShippingAddressIdByReservedQuoteId --- .../Quote/GetQuoteShippingAddressIdByReservedQuoteId.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/GetQuoteShippingAddressIdByReservedQuoteId.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/GetQuoteShippingAddressIdByReservedQuoteId.php index fa42ad4d71fb2..a56949b6f563a 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/GetQuoteShippingAddressIdByReservedQuoteId.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/GetQuoteShippingAddressIdByReservedQuoteId.php @@ -40,13 +40,13 @@ public function __construct( /** * Get quote shipping address id by reserved order id * - * @param string $reversedOrderId + * @param string $reservedOrderId * @return int */ - public function execute(string $reversedOrderId): int + public function execute(string $reservedOrderId): int { $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $reversedOrderId, 'reserved_order_id'); + $this->quoteResource->load($quote, $reservedOrderId, 'reserved_order_id'); return (int)$quote->getShippingAddress()->getId(); } From 061aa982a7acd99294c67d1187e997f96432bb55 Mon Sep 17 00:00:00 2001 From: Evgeny Petrov <evgeny_petrov@epam.com> Date: Tue, 2 Apr 2019 08:20:22 +0300 Subject: [PATCH 311/603] MAGETWO-58764: [GitHub] Minimal Query Length For Catalog Search #6681 --- .../Adapter/Mysql/Query/Builder/Match.php | 37 +++++++++++++++++-- .../Adapter/Mysql/Query/Builder/Match.php | 12 +----- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php b/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php index f5b06d9715d8d..ffdabdb55bee9 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php +++ b/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php @@ -9,8 +9,9 @@ use Magento\Framework\DB\Helper\Mysql\Fulltext; use Magento\Framework\Search\Adapter\Mysql\Field\ResolverInterface; -use Magento\Framework\Search\Adapter\Preprocessor\PreprocessorInterface; use Magento\Framework\Search\Adapter\Mysql\Query\Builder\Match as BuilderMatch; +use Magento\Framework\Search\Adapter\Preprocessor\PreprocessorInterface; +use Magento\Framework\Search\Request\Query\BoolExpression; use Magento\Search\Helper\Data; /** @@ -23,6 +24,11 @@ class Match extends BuilderMatch */ private $searchHelper; + /** + * @var string[] + */ + private $replaceSymbols = []; + /** * @param ResolverInterface $resolver * @param Fulltext $fulltextHelper @@ -44,8 +50,33 @@ public function __construct( /** * @inheritdoc */ - protected function getMinimalCharacterLength() + protected function prepareQuery($queryValue, $conditionType) { - return $this->searchHelper->getMinQueryLength(); + $queryValue = str_replace($this->replaceSymbols, ' ', $queryValue); + foreach ($this->preprocessors as $preprocessor) { + $queryValue = $preprocessor->process($queryValue); + } + + $stringPrefix = ''; + if ($conditionType === BoolExpression::QUERY_CONDITION_MUST) { + $stringPrefix = '+'; + } elseif ($conditionType === BoolExpression::QUERY_CONDITION_NOT) { + $stringPrefix = '-'; + } + + $queryValues = explode(' ', $queryValue); + + foreach ($queryValues as $queryKey => $queryValue) { + if (empty($queryValue)) { + unset($queryValues[$queryKey]); + } else { + $stringSuffix = $this->searchHelper->getMinQueryLength() > strlen($queryValue) ? '' : '*'; + $queryValues[$queryKey] = $stringPrefix . $queryValue . $stringSuffix; + } + } + + $queryValue = implode(' ', $queryValues); + + return $queryValue; } } diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/Builder/Match.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/Builder/Match.php index c881dd9b49079..d4c98cda17e12 100644 --- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/Builder/Match.php +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/Builder/Match.php @@ -148,7 +148,7 @@ protected function prepareQuery($queryValue, $conditionType) if (empty($queryValue)) { unset($queryValues[$queryKey]); } else { - $stringSuffix = $this->getMinimalCharacterLength() > strlen($queryValue) ? '' : '*'; + $stringSuffix = self::MINIMAL_CHARACTER_LENGTH > strlen($queryValue) ? '' : '*'; $queryValues[$queryKey] = $stringPrefix . $queryValue . $stringSuffix; } } @@ -157,14 +157,4 @@ protected function prepareQuery($queryValue, $conditionType) return $queryValue; } - - /** - * Retrieves minimal character length - * - * @return int - */ - protected function getMinimalCharacterLength() - { - return self::MINIMAL_CHARACTER_LENGTH; - } } From 5c5ebc03171d846e3d0488ba5af9395f6bb03ae7 Mon Sep 17 00:00:00 2001 From: Lilit Sargsyan <Lilit_Sargsyan@epam.com> Date: Tue, 2 Apr 2019 10:11:18 +0400 Subject: [PATCH 312/603] MAGETWO-98522: Adding out of stock items to comparison shows success message but fails - Updated automated test script. --- .../AddOutOfStockProductToCompareListTest.xml | 72 +++++++++++++------ .../DisplayOutOfStockProductActionGroup.xml | 9 +++ .../Test/Mftf/Data/InventoryConfigData.xml | 23 ++++++ .../Mftf/Metadata/inventory_config-meta.xml | 22 ++++++ 4 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml create mode 100644 app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml index cc894dcc178aa..7b6f9db8b3ac2 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml @@ -7,12 +7,12 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AddOutOfStockProductToCompareListTest"> <annotations> <features value="Catalog"/> - <title value="Adding to compare list if a product is out of stock"/> - <description value="Adding to compare list if a product is out of stock"/> + <title value="Add out of stock product to compare list"/> + <description value="Add out of stock product to compare list"/> <severity value="MAJOR"/> <testCaseId value="MAGETWO-98644"/> <useCaseId value="MAGETWO-98522"/> @@ -20,42 +20,70 @@ </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <createData entity="ApiCategory" stepKey="category"/> - <createData entity="SimpleOutOfStockProduct" stepKey="product"> + <createData entity="DisableDisplayOutOfStock" stepKey="displayOutOfStockNo"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <createData entity="SimpleSubCategory" stepKey="category"/> + <createData entity="SimpleProduct4" stepKey="product"> <requiredEntity createDataKey="category"/> </createData> </before> <after> + <actionGroup ref="setAsDefaultOutOfStockProduct" stepKey="setAsDefaultOutOfStockProduct"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="product" stepKey="deleteProduct"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> - <amOnPage url="{{AdminLogoutPage.url}}" stepKey="amOnLogoutPage"/> - </after> - - <!--Check 'out of stock' is turned off by default--> - <actionGroup ref="noDisplayOutOfStockProduct" stepKey="noDisplayOutOfStockProduct"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> <!--Open product page--> - <amOnPage url="$$product.name$$.html" stepKey="goToSimpleProductPage"/> + <comment userInput="Open product page" stepKey="openProdPage"/> + <amOnPage url="{{StorefrontProductPage.url($$product.name$$)}}" stepKey="goToSimpleProductPage"/> <waitForPageLoad stepKey="waitForSimpleProductPage"/> - <!--'Add to compare' link is not available--> + <comment userInput="'Add to compare' link is not available" stepKey="addToCompareLinkAvailability"/> <dontSeeElement selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="dontSeeAddToCompareLink"/> - - <!--Turn on 'out of stock' config--> - <actionGroup ref="displayOutOfStockProduct" stepKey="displayOutOfStockProduct"/> - - <!--Clear cache--> - <actionGroup ref="ClearCacheActionGroup" stepKey="clearCache" /> - + <!--Turn on 'out on stock' config--> + <comment userInput="Turn on 'out of stock' config" stepKey="onOutOfStockConfig"/> + <createData entity="EnableDisplayOutOfStock" stepKey="displayOutOfStockYes"/> + <!--Clear cache and reindex--> + <comment userInput="Clear cache and reindex" stepKey="cleanCache"/> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> <!--Open product page--> - <amOnPage url="$$product.name$$.html" stepKey="goToSimpleProductPage2"/> + <comment userInput="Open product page" stepKey="openProductPage"/> + <amOnPage url="{{StorefrontProductPage.url($$product.name$$)}}" stepKey="goToSimpleProductPage2"/> <waitForPageLoad stepKey="waitForSimpleProductPage2"/> - <!--Click on 'Add to Compare' link--> + <comment userInput="Click on 'Add to Compare' link" stepKey="clickOnAddToCompareLink"/> <click selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="clickOnAddToCompare"/> - + <waitForPageLoad stepKey="waitForProdAddToCmpList"/> + <!--Assert success message--> + <comment userInput="Assert success message" stepKey="assertSuccessMsg"/> + <grabTextFrom selector="{{AdminProductMessagesSection.successMessage}}" stepKey="grabTextFromSuccessMessage"/> + <assertEquals expected='You added product $$product.name$$ to the comparison list.' expectedType="string" actual="($grabTextFromSuccessMessage)" stepKey="assertSuccessMessage"/> <!--See product in the comparison list--> + <comment userInput="See product in the comparison list" stepKey="seeProductInComparisonList"/> <amOnPage url="{{StorefrontProductComparePage.url}}" stepKey="navigateToComparePage"/> + <waitForPageLoad stepKey="waitForStorefrontProductComparePageLoad"/> <seeElement selector="{{StorefrontProductCompareMainSection.ProductLinkByName($product.name$)}}" stepKey="seeProductInCompareList"/> + <!--Add product to compare list fom Category page--> + <comment userInput="Add product to compare list fom Category page" stepKey="addToCmpFromCategPage"/> + <amOnPage url="{{StorefrontCategoryPage.url($$category.name$$)}}" stepKey="onCategoryPage"/> + <waitForPageLoad time="30" stepKey="waitForPageLoad1"/> + <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverOverProduct"/> + <click selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="clickAddToCompare"/> + <waitForPageLoad stepKey="waitProdAddingToCmpList"/> + <!--Assert success message--> + <comment userInput="Assert success message" stepKey="assertSuccessMsg2"/> + <grabTextFrom selector="{{AdminProductMessagesSection.successMessage}}" stepKey="grabTextFromSuccessMessage2"/> + <assertEquals expected='You added product $$product.name$$ to the comparison list.' expectedType="string" actual="($grabTextFromSuccessMessage)" stepKey="assertSuccessMessage2"/> + <!--Check that product displays on add to compare widget--> + <comment userInput="Check that product displays on add to compare widget" stepKey="checkProdNameOnWidget"/> + <seeElement selector="{{StorefrontComparisonSidebarSection.ProductTitleByName($$product.name$$)}}" stepKey="seeProdNameOnCmpWidget"/> + <!--See product in the compare page--> + <comment userInput="See product in the compare page" stepKey="seeProductInComparePage"/> + <amOnPage url="{{StorefrontProductComparePage.url}}" stepKey="navigateToComparePage2"/> + <waitForPageLoad stepKey="waitForStorefrontProductComparePageLoad2"/> + <seeElement selector="{{StorefrontProductCompareMainSection.ProductLinkByName($product.name$)}}" stepKey="seeProductInCompareList2"/> </test> </tests> diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml index c7c9126f46803..496284c0a4436 100644 --- a/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml +++ b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml @@ -26,4 +26,13 @@ <selectOption selector="{{InventoryConfigSection.DisplayOutOfStockDropdown}}" userInput="No" stepKey="switchToNo" /> <click selector="{{ContentManagementSection.Save}}" stepKey="clickSaveConfig" /> </actionGroup> + <actionGroup name="setAsDefaultOutOfStockProduct"> + <amOnPage url="{{InventoryConfigurationPage.url}}" stepKey="navigateToInventoryConfigurationPage"/> + <waitForPageLoad time="30" stepKey="waitForConfigPageToLoad"/> + <conditionalClick selector="{{InventoryConfigSection.ProductStockOptionsTab}}" dependentSelector="{{InventoryConfigSection.DisplayOutOfStockSystemValue}}" visible="false" stepKey="expandStockOptions"/> + <waitForElementVisible selector="{{InventoryConfigSection.DisplayOutOfStockSystemValue}}" time="30" stepKey="waitForCheckBoxVisible"/> + <checkOption selector="{{InventoryConfigSection.DisplayOutOfStockSystemValue}}" stepKey="uncheckUseSystemValue"/> + <click selector="{{ContentManagementSection.Save}}" stepKey="clickSaveConfig"/> + <waitForPageLoad time="30" stepKey="waitForConfigPageToLoad2"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml b/app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml new file mode 100644 index 0000000000000..6e0501aeba8ff --- /dev/null +++ b/app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml @@ -0,0 +1,23 @@ +<?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="AdminDisplayOutOfStockYes" type="enable"> + <data key="value">1</data> + </entity> + <entity name="AdminDisplayOutOfStockNo" type="enable"> + <data key="value">0</data> + </entity> + <entity name="EnableDisplayOutOfStock" type="admin_out_of_stock_products_config"> + <requiredEntity type="enable">AdminDisplayOutOfStockYes</requiredEntity> + </entity> + <entity name="DisableDisplayOutOfStock" type="admin_out_of_stock_products_config"> + <requiredEntity type="enable">AdminDisplayOutOfStockNo</requiredEntity> + </entity> +</entities> diff --git a/app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml b/app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml new file mode 100644 index 0000000000000..5898c187bd5e7 --- /dev/null +++ b/app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml @@ -0,0 +1,22 @@ +<?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="AdminOutOfStockProductsConfig" dataType="admin_out_of_stock_products_config" type="create" auth="adminFormKey" url="/admin/system_config/save/section/cataloginventory/" method="POST"> + <object key="groups" dataType="admin_out_of_stock_products_config"> + <object key="options" dataType="admin_out_of_stock_products_config"> + <object key="fields" dataType="admin_out_of_stock_products_config"> + <object key="show_out_of_stock" dataType="enable"> + <field key="value">string</field> + </object> + </object> + </object> + </object> + </operation> +</operations> From 9d0917707b25847598554fdd85d854ade467ce4b Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin <serhiy.yelahin@transoftgroup.com> Date: Tue, 2 Apr 2019 09:24:23 +0300 Subject: [PATCH 313/603] MAGETWO-98886: Gift Card Accounts: expiration date subtracts one day --- lib/internal/Magento/Framework/Data/Form/Element/Date.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Date.php b/lib/internal/Magento/Framework/Data/Form/Element/Date.php index 28e9a18337c68..6e4e97dbac79d 100644 --- a/lib/internal/Magento/Framework/Data/Form/Element/Date.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Date.php @@ -101,7 +101,7 @@ public function setValue($value) try { if (preg_match('/^[0-9]+$/', $value)) { $this->_value = (new \DateTime())->setTimestamp($this->_toTimestamp($value)); - } else if (is_string($value) && $this->isDate($value)) { + } elseif (is_string($value) && $this->isDate($value)) { $this->_value = new \DateTime($value, new \DateTimeZone($this->localeDate->getConfigTimezone())); } else { $this->_value = ''; From 7b6a620b7c3b1b2faf12a190398d7d2f2e3a9644 Mon Sep 17 00:00:00 2001 From: serhii balko <serhii.balko@transoftgroup.com> Date: Tue, 2 Apr 2019 10:52:23 +0300 Subject: [PATCH 314/603] MAGETWO-98335: Unable to find product on product grid page using store view level attribute --- .../Catalog/Ui/DataProvider/Product/ProductCollection.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductCollection.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductCollection.php index 37ac5c85c6f67..e5451c8e49847 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductCollection.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductCollection.php @@ -13,6 +13,8 @@ * Collection which is used for rendering product list in the backend. * * Used for product grid and customizes behavior of the default Product collection for grid needs. + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class ProductCollection extends \Magento\Catalog\Model\ResourceModel\Product\Collection { From 844fc58ba48425d6231a2c55e2f6949102421316 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Tue, 2 Apr 2019 11:18:42 +0300 Subject: [PATCH 315/603] magento/graphql-ce#540: Replace deprecated Magento/Checkout/_files/quote_with_address_saved.php fixture in SetUpsShippingMethodsOnCartTest --- .../Ups/SetUpsShippingMethodsOnCartTest.php | 137 ++++++++++++++++-- 1 file changed, 122 insertions(+), 15 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index 32e9cbf990523..838017b3455df 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -10,7 +10,6 @@ use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\GraphQl\Quote\GetQuoteShippingAddressIdByReservedQuoteId; use Magento\Integration\Api\CustomerTokenServiceInterface; -use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -20,19 +19,14 @@ class SetUpsShippingMethodsOnCartTest extends GraphQlAbstract { /** - * Defines carrier code for "UPS" shipping method - */ - const CARRIER_CODE = 'ups'; - - /** - * Defines method code for the "Ground" UPS shipping + * Defines carrier label for "UPS" shipping method */ - const CARRIER_METHOD_CODE_GROUND = 'GND'; + const CARRIER_LABEL = 'United Parcel Service'; /** - * @var GetQuoteShippingAddressIdByReservedQuoteId + * Defines carrier code for "UPS" shipping method */ - private $getQuoteShippingAddressIdByReservedQuoteId; + const CARRIER_CODE = 'ups'; /** * @var CustomerTokenServiceInterface @@ -44,6 +38,11 @@ class SetUpsShippingMethodsOnCartTest extends GraphQlAbstract */ private $getMaskedQuoteIdByReservedOrderId; + /** + * @var GetQuoteShippingAddressIdByReservedQuoteId + */ + private $getQuoteShippingAddressIdByReservedQuoteId; + /** * @inheritdoc */ @@ -57,13 +56,17 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/products.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php + * + * @param string $carrierMethodCode + * @param string $carrierMethodLabel + * @dataProvider availableForCartShippingMethods */ - public function testSetUpsShippingMethod() + public function testSetAvailableForCartUpsShippingMethod(string $carrierMethodCode, string $carrierMethodLabel) { $quoteReservedId = 'test_quote'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); @@ -73,19 +76,123 @@ public function testSetUpsShippingMethod() $maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, - self::CARRIER_METHOD_CODE_GROUND + $carrierMethodCode ); $response = $this->sendRequestWithToken($query); + $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses']; $expectedResult = [ 'carrier_code' => self::CARRIER_CODE, - 'method_code' => self::CARRIER_METHOD_CODE_GROUND, - 'label' => 'United Parcel Service - Ground', + 'method_code' => $carrierMethodCode, + 'label' => self::CARRIER_LABEL . ' - ' . $carrierMethodLabel, ]; self::assertEquals($addressesInformation[0]['selected_shipping_method'], $expectedResult); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php + * + * @param string $carrierMethodCode + * @param string $carrierMethodLabel + * @dataProvider notAvailableForCartShippingMethods + */ + public function testSetNotAvailableForCartUpsShippingMethod(string $carrierMethodCode, string $carrierMethodLabel) + { + $quoteReservedId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); + $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); + + $query = $this->getQuery( + $maskedQuoteId, + $shippingAddressId, + self::CARRIER_CODE, + $carrierMethodCode + ); + + $this->expectExceptionMessage( + "GraphQL response contains errors: Carrier with such method not found: " . self::CARRIER_CODE . ", " . $carrierMethodCode + ); + + $response = $this->sendRequestWithToken($query); + + $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses']; + $expectedResult = [ + 'carrier_code' => self::CARRIER_CODE, + 'method_code' => $carrierMethodCode, + 'label' => self::CARRIER_LABEL . ' - ' . $carrierMethodLabel, + ]; + self::assertEquals($addressesInformation[0]['selected_shipping_method'], $expectedResult); + } + + /** + * @return array + */ + public function availableForCartShippingMethods(): array + { + $shippingMethods = ['1DM', '1DA', '2DA', '3DS', 'GND']; + + return $this->filterShippingMethodsByCodes($shippingMethods); + } + + /** + * @return array + */ + public function notAvailableForCartShippingMethods(): array + { + $shippingMethods = ['1DML', '1DAL', '1DAPI', '1DP', '1DPL', '2DM', '2DML', '2DAL', 'GNDCOM', 'GNDRES', 'STD', 'XPR', 'WXS', 'XPRL', 'XDM', 'XDML', 'XPD']; + + return $this->filterShippingMethodsByCodes($shippingMethods); + } + + /** + * @param array $filter + * @return array + */ + private function filterShippingMethodsByCodes(array $filter):array + { + $result = []; + foreach ($this->getAllUpsShippingMethods() as $shippingMethod) { + if (in_array($shippingMethod[0], $filter)) { + $result[] = $shippingMethod; + } + } + return $result; + } + + private function getAllUpsShippingMethods():array + { + return [ + ['1DM', 'Next Day Air Early AM'], + ['1DML', 'Next Day Air Early AM Letter'], + ['1DA', 'Next Day Air'], + ['1DAL', 'Next Day Air Letter'], + ['1DAPI', 'Next Day Air Intra (Puerto Rico)'], + ['1DP', 'Next Day Air Saver'], + ['1DPL', 'Next Day Air Saver Letter'], + ['2DM', '2nd Day Air AM'], + ['2DML', '2nd Day Air AM Letter'], + ['2DA', '2nd Day Air'], + ['2DAL', '2nd Day Air Letter'], + ['3DS', '3 Day Select'], + ['GND', 'Ground'], + ['GNDCOM', 'Ground Commercial'], + ['GNDRES', 'Ground Residential'], + ['STD', 'Canada Standard'], + ['XPR', 'Worldwide Express'], + ['WXS', 'Worldwide Express Saver'], + ['XPRL', 'Worldwide Express Letter'], + ['XDM', 'Worldwide Express Plus'], + ['XDML', 'Worldwide Express Plus Letter'], + ['XPD', 'Worldwide Expedited'], + ]; + } + /** * Generates query for setting the specified shipping method on cart * From 5b1789ed84192f73d0bb3f04e6d4c9e7db279d03 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Tue, 2 Apr 2019 11:32:13 +0300 Subject: [PATCH 316/603] magento/graphql-ce#559: Fix misspelling in GetQuoteShippingAddressIdByReservedQuoteId --- .../Quote/Customer/SetBillingAddressOnCartTest.php | 6 +++--- .../Quote/Customer/SetShippingAddressOnCartTest.php | 6 +++--- .../Quote/Customer/SetShippingMethodsOnCartTest.php | 12 ++++++------ .../Quote/GetMaskedQuoteIdByReservedOrderId.php | 6 +++--- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php index 88e7b93dd1d08..46e4fed4c113d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php @@ -568,16 +568,16 @@ private function getHeaderMap(string $username = 'customer@example.com', string } /** - * @param string $reversedOrderId + * @param string $reservedOrderId * @param int $customerId * @return string */ private function assignQuoteToCustomer( - string $reversedOrderId = 'test_order_with_simple_product_without_address', + string $reservedOrderId = 'test_order_with_simple_product_without_address', int $customerId = 1 ): string { $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $reversedOrderId, 'reserved_order_id'); + $this->quoteResource->load($quote, $reservedOrderId, 'reserved_order_id'); $quote->setCustomerId($customerId); $this->quoteResource->save($quote); return $this->quoteIdToMaskedId->execute((int)$quote->getId()); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php index 5ff29d20b34d7..a47aeed1f2fee 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php @@ -541,16 +541,16 @@ private function getHeaderMap(string $username = 'customer@example.com', string } /** - * @param string $reversedOrderId + * @param string $reservedOrderId * @param int $customerId * @return string */ private function assignQuoteToCustomer( - string $reversedOrderId = 'test_order_with_simple_product_without_address', + string $reservedOrderId = 'test_order_with_simple_product_without_address', int $customerId = 1 ): string { $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $reversedOrderId, 'reserved_order_id'); + $this->quoteResource->load($quote, $reservedOrderId, 'reserved_order_id'); $quote->setCustomerId($customerId); $this->quoteResource->save($quote); return $this->quoteIdToMaskedId->execute((int)$quote->getId()); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php index b5634f51cb366..a01761363e42b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php @@ -162,30 +162,30 @@ private function prepareMutationQuery( } /** - * @param string $reversedOrderId + * @param string $reservedOrderId * @return string * @SuppressWarnings(PHPMD.UnusedPrivateMethod) */ - private function getMaskedQuoteIdByReservedOrderId(string $reversedOrderId): string + private function getMaskedQuoteIdByReservedOrderId(string $reservedOrderId): string { $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $reversedOrderId, 'reserved_order_id'); + $this->quoteResource->load($quote, $reservedOrderId, 'reserved_order_id'); return $this->quoteIdToMaskedId->execute((int)$quote->getId()); } /** - * @param string $reversedOrderId + * @param string $reservedOrderId * @param int $customerId * @return string * @SuppressWarnings(PHPMD.UnusedPrivateMethod) */ private function assignQuoteToCustomer( - string $reversedOrderId, + string $reservedOrderId, int $customerId ): string { $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $reversedOrderId, 'reserved_order_id'); + $this->quoteResource->load($quote, $reservedOrderId, 'reserved_order_id'); $quote->setCustomerId($customerId); $this->quoteResource->save($quote); return $this->quoteIdToMaskedId->execute((int)$quote->getId()); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/GetMaskedQuoteIdByReservedOrderId.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/GetMaskedQuoteIdByReservedOrderId.php index eab362c3a0a6f..9bb9bef9bdb09 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/GetMaskedQuoteIdByReservedOrderId.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/GetMaskedQuoteIdByReservedOrderId.php @@ -50,14 +50,14 @@ public function __construct( /** * Get masked quote id by reserved order id * - * @param string $reversedOrderId + * @param string $reservedOrderId * @return string * @throws NoSuchEntityException */ - public function execute(string $reversedOrderId): string + public function execute(string $reservedOrderId): string { $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $reversedOrderId, 'reserved_order_id'); + $this->quoteResource->load($quote, $reservedOrderId, 'reserved_order_id'); return $this->quoteIdToMaskedId->execute((int)$quote->getId()); } From cb0ed4012a022ad32045d80e7e3f7780b4072ba0 Mon Sep 17 00:00:00 2001 From: Veronika Kurochkina <veronika_kurochkina@epam.com> Date: Tue, 2 Apr 2019 11:45:51 +0300 Subject: [PATCH 317/603] MAGETWO-58226: Calendar Custom Options are displayed broken on Storefront if JS validation is performed - Fix static --- .../Magento/Catalog/Test/Block/Product/View/CustomOptions.php | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php index 99ff9b73b92eb..4e8e0f97d70d5 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php @@ -149,6 +149,7 @@ public function getOptions(FixtureInterface $product) foreach ($dataOptions as $option) { $title = $option['title']; if (!isset($listCustomOptions[$title])) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception("Can't find option: \"{$title}\""); } From 3eb35194059903766b5eb7bb14e7d8d1c67e4f5f Mon Sep 17 00:00:00 2001 From: Veronika Kurochkina <veronika_kurochkina@epam.com> Date: Tue, 2 Apr 2019 11:58:48 +0300 Subject: [PATCH 318/603] MAGETWO-65232: Product name does not display special characters properly - Updated automated test script. --- .../Mftf/Test/AdminRemoveImageAffectsAllScopesTest.xml | 2 -- .../Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml | 9 --------- 2 files changed, 11 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageAffectsAllScopesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageAffectsAllScopesTest.xml index 85c54e0942c74..8316f54c15a52 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageAffectsAllScopesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageAffectsAllScopesTest.xml @@ -65,10 +65,8 @@ </actionGroup> <deleteData createDataKey="category" stepKey="deletePreReqCategory"/> <deleteData createDataKey="product" stepKey="deleteFirstProduct"/> - <magentoCLI stepKey="reindex" command="indexer:reindex"/> <magentoCLI stepKey="flushCache" command="cache:flush"/> - <actionGroup ref="logout" stepKey="logout"/> </after> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml index 7c971f3b04457..b90bac7e0881b 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml @@ -19,18 +19,15 @@ <see selector="{{AdminInvoiceOrderInformationSection.customerName}}" userInput="{{customer.firstname}}" stepKey="seeCustomerName"/> <see selector="{{AdminInvoiceOrderInformationSection.customerEmail}}" userInput="{{customer.email}}" stepKey="seeCustomerEmail"/> <see selector="{{AdminInvoiceOrderInformationSection.customerGroup}}" userInput="{{customerGroup.code}}" stepKey="seeCustomerGroup"/> - <see selector="{{AdminInvoiceAddressInformationSection.billingAddress}}" userInput="{{billingAddress.street[0]}}" stepKey="seeBillingAddressStreet"/> <see selector="{{AdminInvoiceAddressInformationSection.billingAddress}}" userInput="{{billingAddress.city}}" stepKey="seeBillingAddressCity"/> <see selector="{{AdminInvoiceAddressInformationSection.billingAddress}}" userInput="{{billingAddress.country_id}}" stepKey="seeBillingAddressCountry"/> <see selector="{{AdminInvoiceAddressInformationSection.billingAddress}}" userInput="{{billingAddress.postcode}}" stepKey="seeBillingAddressPostcode"/> - <see selector="{{AdminInvoiceAddressInformationSection.shippingAddress}}" userInput="{{shippingAddress.street[0]}}" stepKey="seeShippingAddressStreet"/> <see selector="{{AdminInvoiceAddressInformationSection.shippingAddress}}" userInput="{{shippingAddress.city}}" stepKey="seeShippingAddressCity"/> <see selector="{{AdminInvoiceAddressInformationSection.shippingAddress}}" userInput="{{shippingAddress.country_id}}" stepKey="seeShippingAddressCountry"/> <see selector="{{AdminInvoiceAddressInformationSection.shippingAddress}}" userInput="{{shippingAddress.postcode}}" stepKey="seeShippingAddressPostcode"/> </actionGroup> - <!--Check that product is in invoice items--> <actionGroup name="seeProductInInvoiceItems"> <arguments> @@ -38,7 +35,6 @@ </arguments> <see selector="{{AdminInvoiceItemsSection.skuColumn}}" userInput="{{product.sku}}" stepKey="seeProductSkuInGrid"/> </actionGroup> - <!--Admin Fast Create Invoice--> <actionGroup name="adminFastCreateInvoice"> <click selector="{{AdminOrderDetailsMainActionsSection.invoice}}" stepKey="clickInvoiceButton"/> @@ -50,26 +46,22 @@ <click selector="{{AdminOrderInvoicesTabSection.viewInvoice}}" stepKey="openInvoicePage"/> <waitForPageLoad stepKey="waitForInvoicePageLoad"/> </actionGroup> - <actionGroup name="clearInvoicesGridFilters"> <amOnPage url="{{AdminInvoicesPage.url}}" stepKey="goToInvoices"/> <waitForPageLoad stepKey="waitInvoicesGridToLoad"/> <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearFilters" /> <waitForPageLoad stepKey="waitInvoicesGrid"/> </actionGroup> - <actionGroup name="goToInvoiceIntoOrder"> <click selector="{{AdminOrderDetailsMainActionsSection.invoice}}" stepKey="clickInvoiceAction"/> <seeInCurrentUrl url="{{AdminInvoiceNewPage.url}}" stepKey="seeOrderInvoiceUrl"/> <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Invoice" stepKey="seePageNameNewInvoicePage"/> </actionGroup> - <actionGroup name="StartCreateInvoiceFromOrderPage"> <click selector="{{AdminOrderDetailsMainActionsSection.invoice}}" stepKey="clickInvoiceAction"/> <seeInCurrentUrl url="{{AdminInvoiceNewPage.url}}" stepKey="seeNewInvoiceUrl"/> <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Invoice" stepKey="seeNewInvoicePageTitle"/> </actionGroup> - <actionGroup name="SubmitInvoice"> <click selector="{{AdminInvoiceMainActionsSection.submitInvoice}}" stepKey="clickSubmitInvoice"/> <waitForElementVisible selector="{{AdminMessagesSection.successMessage}}" stepKey="waitForMessageAppears"/> @@ -77,7 +69,6 @@ <grabFromCurrentUrl regex="~/order_id/(\d+)/~" stepKey="grabOrderId"/> <seeInCurrentUrl url="{{AdminOrderDetailsPage.url('$grabOrderId')}}" stepKey="seeViewOrderPageInvoice"/> </actionGroup> - <!--Filter invoices by order id --> <actionGroup name="filterInvoiceGridByOrderId"> <arguments> From 5fd06db19bdf5cfbf8ea4c7f956b2d4bd200d4d1 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Tue, 2 Apr 2019 12:23:11 +0300 Subject: [PATCH 319/603] MAGETWO-64838: Unable to create order from store front if customer address custom attribute is required. - Fixed static tests; --- lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php index f93d7efda5c8a..c253a400bed93 100644 --- a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php +++ b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php @@ -275,6 +275,7 @@ protected function _createFromArray($className, $data) } else { $setterValue = $this->convertValue($value, $returnType); } + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (SerializationException $e) { throw new SerializationException( new Phrase( @@ -323,6 +324,7 @@ protected function convertCustomAttributeValue($customAttributesValueArray, $dat ) { try { $attributeValue = $this->convertValue($customAttributeValue, $type); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (SerializationException $e) { throw new SerializationException( new Phrase( From 1f3d9bc261b6d2038c31737446533c8796777b1f Mon Sep 17 00:00:00 2001 From: Evgeny Petrov <evgeny_petrov@epam.com> Date: Tue, 2 Apr 2019 14:22:09 +0300 Subject: [PATCH 320/603] MAGETWO-58764: [GitHub] Minimal Query Length For Catalog Search #6681 --- .../Mftf/ActionGroup/AdminSetMinimalQueryLengthActionGroup.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/AdminSetMinimalQueryLengthActionGroup.xml b/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/AdminSetMinimalQueryLengthActionGroup.xml index e60be3729834a..b9ef37cb4effe 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/AdminSetMinimalQueryLengthActionGroup.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/AdminSetMinimalQueryLengthActionGroup.xml @@ -21,7 +21,6 @@ <see userInput="{{MinMaxQueryLength.Hint}}" selector="{{AdminCatalogSearchConfigurationSection.maxQueryLengthHint}}" stepKey="seeHint2"/> <uncheckOption selector="{{AdminCatalogSearchConfigurationSection.minQueryLengthInherit}}" stepKey="uncheckSystemValue"/> <fillField selector="{{AdminCatalogSearchConfigurationSection.minQueryLength}}" userInput="{{minLength}}" stepKey="setMinQueryLength"/> - <scrollTo selector="{{AdminConfigCatalogCategoryPermissionsSection.catalogPermissionsTab}}" stepKey="scrollToCatalogPermissionsTab"/> <click selector="{{AdminCatalogSearchConfigurationSection.catalogSearchTab}}" stepKey="collapseTab"/> <click selector="{{ContentManagementSection.Save}}" stepKey="saveConfig"/> <waitForPageLoad stepKey="waitForConfigSaved"/> From a6ef1186bf5003b6e9868eb96ab36d079407b3a9 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 2 Apr 2019 15:03:07 +0300 Subject: [PATCH 321/603] magento/magento2#21767: Static test fix. --- .../Framework/Event/Test/Unit/Invoker/InvokerDefaultTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/internal/Magento/Framework/Event/Test/Unit/Invoker/InvokerDefaultTest.php b/lib/internal/Magento/Framework/Event/Test/Unit/Invoker/InvokerDefaultTest.php index b339ed55bf691..e6ec123823854 100644 --- a/lib/internal/Magento/Framework/Event/Test/Unit/Invoker/InvokerDefaultTest.php +++ b/lib/internal/Magento/Framework/Event/Test/Unit/Invoker/InvokerDefaultTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Framework\Event\Test\Unit\Invoker; +/** + * Test for Magento\Framework\Event\Invoker\InvokerDefault. + */ class InvokerDefaultTest extends \PHPUnit\Framework\TestCase { /** From 87ec9055992ea6c42b9f04789086332b1c8dc8f6 Mon Sep 17 00:00:00 2001 From: Ivan Gerchak <ivang@ven.com> Date: Tue, 2 Apr 2019 15:42:12 +0300 Subject: [PATCH 322/603] Remove creating $target --- lib/web/fotorama/fotorama.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/web/fotorama/fotorama.js b/lib/web/fotorama/fotorama.js index b63b9cd872be7..b38e70d915c9d 100644 --- a/lib/web/fotorama/fotorama.js +++ b/lib/web/fotorama/fotorama.js @@ -1443,8 +1443,7 @@ fotoramaVersion = '4.6.4'; return; } - $target = $(e.target); - isDisabledSwipe = $target.hasClass('disableSwipe'); + isDisabledSwipe = $(e.target).hasClass('disableSwipe'); if (isDisabledSwipe) { return; From 3e0836e142b3e48c9d3644e8e1a6044a31aeeaad Mon Sep 17 00:00:00 2001 From: Yuriy <yvechirko@magecom.net> Date: Tue, 2 Apr 2019 16:13:58 +0300 Subject: [PATCH 323/603] Previous scrolling to invalid form element is not being canceled on hitting submit multiple times #21715 --- lib/web/mage/validation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index a57191fd4aff4..73c5ef4d4f02f 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1958,7 +1958,7 @@ } if (firstActive.length) { - $('html, body').animate({ + $('html, body').stop().animate({ scrollTop: firstActive.offset().top }); firstActive.focus(); From 0c3d6b75e0c45d31e75119e26015e4f6f1e7516d Mon Sep 17 00:00:00 2001 From: Evgeny Petrov <evgeny_petrov@epam.com> Date: Tue, 2 Apr 2019 16:14:59 +0300 Subject: [PATCH 324/603] MAGETWO-58764: [GitHub] Minimal Query Length For Catalog Search #6681 --- .../Model/Search/Adapter/Mysql/Query/Builder/Match.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php b/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php index ffdabdb55bee9..8f5aa73e9d12c 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php +++ b/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php @@ -44,6 +44,7 @@ public function __construct( array $preprocessors = [] ) { parent::__construct($resolver, $fulltextHelper, $fulltextSearchMode, $preprocessors); + $this->replaceSymbols = str_split(self::SPECIAL_CHARACTERS, 1); $this->searchHelper = $searchHelper; } From e0ae403cd85e45139f003b58f8dc0626c54ba3b1 Mon Sep 17 00:00:00 2001 From: Lilit Sargsyan <Lilit_Sargsyan@epam.com> Date: Tue, 2 Apr 2019 18:01:28 +0400 Subject: [PATCH 325/603] MAGETWO-98522: Adding out of stock items to comparison shows success message but fails - Updated automated test script. --- .../AddOutOfStockProductToCompareListTest.xml | 17 +++++++++----- .../DisplayOutOfStockProductActionGroup.xml | 9 -------- .../Test/Mftf/Data/InventoryConfigData.xml | 23 ------------------- .../Mftf/Metadata/inventory_config-meta.xml | 22 ------------------ 4 files changed, 11 insertions(+), 60 deletions(-) delete mode 100644 app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml delete mode 100644 app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml index 7b6f9db8b3ac2..4f66395bd0fbf 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml @@ -20,7 +20,7 @@ </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <createData entity="DisableDisplayOutOfStock" stepKey="displayOutOfStockNo"/> + <magentoCLI command="config:set cataloginventory/options/show_out_of_stock 0" stepKey="displayOutOfStockNo"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <createData entity="SimpleSubCategory" stepKey="category"/> <createData entity="SimpleProduct4" stepKey="product"> @@ -28,12 +28,11 @@ </createData> </before> <after> - <actionGroup ref="setAsDefaultOutOfStockProduct" stepKey="setAsDefaultOutOfStockProduct"/> + <magentoCLI command="config:set cataloginventory/options/show_out_of_stock 0" stepKey="displayOutOfStockNo2"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="product" stepKey="deleteProduct"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> <actionGroup ref="logout" stepKey="logout"/> - </after> <!--Open product page--> <comment userInput="Open product page" stepKey="openProdPage"/> @@ -44,7 +43,7 @@ <dontSeeElement selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="dontSeeAddToCompareLink"/> <!--Turn on 'out on stock' config--> <comment userInput="Turn on 'out of stock' config" stepKey="onOutOfStockConfig"/> - <createData entity="EnableDisplayOutOfStock" stepKey="displayOutOfStockYes"/> + <magentoCLI command="config:set cataloginventory/options/show_out_of_stock 1" stepKey="displayOutOfStockYes"/> <!--Clear cache and reindex--> <comment userInput="Clear cache and reindex" stepKey="cleanCache"/> <magentoCLI command="indexer:reindex" stepKey="reindex"/> @@ -66,10 +65,16 @@ <amOnPage url="{{StorefrontProductComparePage.url}}" stepKey="navigateToComparePage"/> <waitForPageLoad stepKey="waitForStorefrontProductComparePageLoad"/> <seeElement selector="{{StorefrontProductCompareMainSection.ProductLinkByName($product.name$)}}" stepKey="seeProductInCompareList"/> - <!--Add product to compare list fom Category page--> - <comment userInput="Add product to compare list fom Category page" stepKey="addToCmpFromCategPage"/> + <!--Go to Category page and delete product from comparison list--> + <comment userInput="Go to Category page and delete prduct from comparison list" stepKey="deletProdFromCmpList"/> <amOnPage url="{{StorefrontCategoryPage.url($$category.name$$)}}" stepKey="onCategoryPage"/> <waitForPageLoad time="30" stepKey="waitForPageLoad1"/> + <click selector="{{StorefrontComparisonSidebarSection.ClearAll}}" stepKey="clickClearAll"/> + <waitForPageLoad time="30" stepKey="waitForConfirmPageLoad"/> + <click selector="{{AdminDeleteRoleSection.confirm}}" stepKey="confirmProdDelate"/> + <waitForPageLoad time="30" stepKey="waitForConfirmLoad"/> + <!--Add product to compare list from Category page--> + <comment userInput="Add product to compare list fom Category page" stepKey="addToCmpFromCategPage"/> <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverOverProduct"/> <click selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="clickAddToCompare"/> <waitForPageLoad stepKey="waitProdAddingToCmpList"/> diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml index 496284c0a4436..c7c9126f46803 100644 --- a/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml +++ b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/DisplayOutOfStockProductActionGroup.xml @@ -26,13 +26,4 @@ <selectOption selector="{{InventoryConfigSection.DisplayOutOfStockDropdown}}" userInput="No" stepKey="switchToNo" /> <click selector="{{ContentManagementSection.Save}}" stepKey="clickSaveConfig" /> </actionGroup> - <actionGroup name="setAsDefaultOutOfStockProduct"> - <amOnPage url="{{InventoryConfigurationPage.url}}" stepKey="navigateToInventoryConfigurationPage"/> - <waitForPageLoad time="30" stepKey="waitForConfigPageToLoad"/> - <conditionalClick selector="{{InventoryConfigSection.ProductStockOptionsTab}}" dependentSelector="{{InventoryConfigSection.DisplayOutOfStockSystemValue}}" visible="false" stepKey="expandStockOptions"/> - <waitForElementVisible selector="{{InventoryConfigSection.DisplayOutOfStockSystemValue}}" time="30" stepKey="waitForCheckBoxVisible"/> - <checkOption selector="{{InventoryConfigSection.DisplayOutOfStockSystemValue}}" stepKey="uncheckUseSystemValue"/> - <click selector="{{ContentManagementSection.Save}}" stepKey="clickSaveConfig"/> - <waitForPageLoad time="30" stepKey="waitForConfigPageToLoad2"/> - </actionGroup> </actionGroups> diff --git a/app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml b/app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml deleted file mode 100644 index 6e0501aeba8ff..0000000000000 --- a/app/code/Magento/Config/Test/Mftf/Data/InventoryConfigData.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?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="AdminDisplayOutOfStockYes" type="enable"> - <data key="value">1</data> - </entity> - <entity name="AdminDisplayOutOfStockNo" type="enable"> - <data key="value">0</data> - </entity> - <entity name="EnableDisplayOutOfStock" type="admin_out_of_stock_products_config"> - <requiredEntity type="enable">AdminDisplayOutOfStockYes</requiredEntity> - </entity> - <entity name="DisableDisplayOutOfStock" type="admin_out_of_stock_products_config"> - <requiredEntity type="enable">AdminDisplayOutOfStockNo</requiredEntity> - </entity> -</entities> diff --git a/app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml b/app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.xml deleted file mode 100644 index 5898c187bd5e7..0000000000000 --- a/app/code/Magento/Config/Test/Mftf/Metadata/inventory_config-meta.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. - */ ---> - -<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataOperation.xsd"> - <operation name="AdminOutOfStockProductsConfig" dataType="admin_out_of_stock_products_config" type="create" auth="adminFormKey" url="/admin/system_config/save/section/cataloginventory/" method="POST"> - <object key="groups" dataType="admin_out_of_stock_products_config"> - <object key="options" dataType="admin_out_of_stock_products_config"> - <object key="fields" dataType="admin_out_of_stock_products_config"> - <object key="show_out_of_stock" dataType="enable"> - <field key="value">string</field> - </object> - </object> - </object> - </object> - </operation> -</operations> From a448ee502f8ede1b34e133572ce6fc0e52440846 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Tue, 2 Apr 2019 10:13:42 -0500 Subject: [PATCH 326/603] MC-15439: Deferred loading / parsing of JS --- app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php index 19ef31b2a41b4..a81f29280af96 100644 --- a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php @@ -20,8 +20,7 @@ public function beforeSendResponse(\Magento\Framework\App\Response\Http $subject { $content = $subject->getContent(); $script = []; - if (strpos($content, '</body') > 0) { - $content = preg_replace('#<!--(?!\s?/?ko).*?-->#s', '', $content); + if (strpos($content, '</body') !== false) { $pattern = '#<script[^>]*+(?<!text/x-magento-template.)>.*?</script>#is'; $content = preg_replace_callback( $pattern, @@ -36,4 +35,4 @@ function ($matchPart) use (&$script) { ); } } -} \ No newline at end of file +} From 4c002ee963b7ae6e72189412c2c431d138428489 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Tue, 2 Apr 2019 10:45:59 -0500 Subject: [PATCH 327/603] Minor fixes for magento/magento-functional-tests-migration#686 - update test annotations - provided additional verification of CAPTCHA --- ...tVisibleOnCustomerLoginFormActionGroup.xml | 22 ++++++ ...aVisibleOnCustomerLoginFormActionGroup.xml | 21 +++++ ...ustomerLoginFormWithCaptchaActionGroup.xml | 17 ++++ .../StorefrontCustomerSignInFormSection.xml | 2 +- ...orefrontCustomerSignInPopupFormSection.xml | 16 ++++ .../Test/CaptchaOnStoreFrontLoginTest.xml | 62 --------------- .../StorefrontCaptchaOnCustomerLoginTest.xml | 79 +++++++++++++++++++ .../AssertCustomerLoggedInActionGroup.xml | 17 ++++ .../AssertMessageCustomerLoginActionGroup.xml | 18 +++++ ...lickSignOnCustomerLoginFormActionGroup.xml | 15 ++++ ...efrontFillCustomerLoginFormActionGroup.xml | 19 +++++ ...efrontOpenCustomerLoginPageActionGroup.xml | 15 ++++ ...StorefrontCustomerLoginMessagesSection.xml | 1 + .../StorefrontCustomerSignInFormSection.xml | 5 +- .../Section/StorefrontPanelHeaderSection.xml | 3 + 15 files changed, 245 insertions(+), 67 deletions(-) create mode 100644 app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaNotVisibleOnCustomerLoginFormActionGroup.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerLoginFormActionGroup.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontFillCustomerLoginFormWithCaptchaActionGroup.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerSignInPopupFormSection.xml delete mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontLoginTest.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnCustomerLoginTest.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerLoggedInActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertMessageCustomerLoginActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontClickSignOnCustomerLoginFormActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillCustomerLoginFormActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerLoginPageActionGroup.xml diff --git a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaNotVisibleOnCustomerLoginFormActionGroup.xml b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaNotVisibleOnCustomerLoginFormActionGroup.xml new file mode 100644 index 0000000000000..a371f177e3552 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaNotVisibleOnCustomerLoginFormActionGroup.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="AssertCaptchaNotVisibleOnCustomerLoginFormActionGroup"> + <waitForPageLoad stepKey="waitForPageLoaded" /> + <dontSee selector="{{StorefrontCustomerSignInFormSection.captchaField}}" stepKey="dontSeeCaptchaField"/> + <dontSee selector="{{StorefrontCustomerSignInFormSection.captchaImg}}" stepKey="dontSeeCaptchaImage"/> + <dontSee selector="{{StorefrontCustomerSignInFormSection.captchaReload}}" stepKey="dontSeeCaptchaReloadButton"/> + <reloadPage stepKey="refreshPage"/> + <waitForPageLoad stepKey="waitForPageReloaded" /> + <dontSee selector="{{StorefrontCustomerSignInFormSection.captchaField}}" stepKey="dontSeeCaptchaFieldAfterPageReload"/> + <dontSee selector="{{StorefrontCustomerSignInFormSection.captchaImg}}" stepKey="dontSeeCaptchaImageAfterPageReload"/> + <dontSee selector="{{StorefrontCustomerSignInFormSection.captchaReload}}" stepKey="dontSeeCaptchaReloadButtonAfterPageReload"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerLoginFormActionGroup.xml b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerLoginFormActionGroup.xml new file mode 100644 index 0000000000000..5616b099c026d --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerLoginFormActionGroup.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="AssertCaptchaVisibleOnCustomerLoginFormActionGroup"> + <waitForElementVisible selector="{{StorefrontCustomerSignInFormSection.captchaField}}" stepKey="waitToSeeCaptchaField"/> + <waitForElementVisible selector="{{StorefrontCustomerSignInFormSection.captchaImg}}" stepKey="waitToSeeCaptchaImage"/> + <waitForElementVisible selector="{{StorefrontCustomerSignInFormSection.captchaReload}}" stepKey="waitToSeeCaptchaReloadButton"/> + <reloadPage stepKey="refreshPage"/> + <waitForPageLoad stepKey="waitForPageReloaded" /> + <waitForElementVisible selector="{{StorefrontCustomerSignInFormSection.captchaField}}" stepKey="waitToSeeCaptchaFieldAfterPageReload"/> + <waitForElementVisible selector="{{StorefrontCustomerSignInFormSection.captchaImg}}" stepKey="waitToSeeCaptchaImageAfterPageReload"/> + <waitForElementVisible selector="{{StorefrontCustomerSignInFormSection.captchaReload}}" stepKey="waitToSeeCaptchaReloadButtonAfterPageReload"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontFillCustomerLoginFormWithCaptchaActionGroup.xml b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontFillCustomerLoginFormWithCaptchaActionGroup.xml new file mode 100644 index 0000000000000..5ad727a8fe99d --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontFillCustomerLoginFormWithCaptchaActionGroup.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="StorefrontFillCustomerLoginFormWithCaptchaActionGroup" extends="StorefrontFillCustomerLoginFormActionGroup"> + <arguments> + <argument name="captcha" type="string" /> + </arguments> + <fillField stepKey="fillCaptchaField" after="fillPassword" userInput="{{captcha}}" selector="{{StorefrontCustomerSignInFormSection.captchaField}}" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml index 7a0557c4a2744..54aa36d1ca267 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml @@ -8,7 +8,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> - <section name="StorefrontCustomerSignInPopupFormSection"> + <section name="StorefrontCustomerSignInFormSection"> <element name="captchaField" type="input" selector="#captcha_user_login"/> <element name="captchaImg" type="block" selector=".captcha-img"/> <element name="captchaReload" type="block" selector=".captcha-reload"/> diff --git a/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerSignInPopupFormSection.xml b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerSignInPopupFormSection.xml new file mode 100644 index 0000000000000..7a0557c4a2744 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontCustomerSignInPopupFormSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontCustomerSignInPopupFormSection"> + <element name="captchaField" type="input" selector="#captcha_user_login"/> + <element name="captchaImg" type="block" selector=".captcha-img"/> + <element name="captchaReload" type="block" selector=".captcha-reload"/> + </section> +</sections> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontLoginTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontLoginTest.xml deleted file mode 100644 index 59de69b1d2b0d..0000000000000 --- a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontLoginTest.xml +++ /dev/null @@ -1,62 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="CaptchaOnStoreFrontLoginTest"> - <annotations> - <features value="Captcha"/> - <stories value="Check CAPTCHA on Storefront Login Page."/> - <title value="Captcha customer login page test"/> - <description value="Check CAPTCHA on Storefront Login Page."/> - <severity value="MAJOR"/> - <group value="captcha"/> - <group value="mtf_migrated"/> - </annotations> - <before> - <createData entity="Simple_US_Customer" stepKey="customer"/> - </before> - <after> - <deleteData createDataKey="customer" stepKey="deleteCustomer"/> - </after> - - <!-- Open storefront login form --> - <amOnPage url="{{StorefrontCustomerSignInPage.url}}" stepKey="amOnSignInPage"/> - <waitForPageLoad stepKey="waitForStorefrontLoginPage"/> - - <!-- Login with wrong credentials 3 times --> - <fillField selector="{{StorefrontCustomerSignInFormSection.emailField}}" userInput="$$customer.email$$" stepKey="fillEmail1"/> - <fillField selector="{{StorefrontCustomerSignInFormSection.passwordField}}" userInput="$$customer.password$$INVALID" stepKey="fillPassword1" /> - <click selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}" stepKey="clickSignInAccountButton1"/> - <see selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." stepKey="seeErrorMessage1" /> - <dontSee selector="StorefrontCustomerSignInFormSection.captchaField" stepKey="dontSeeCaptchaInputField1"/> - - <fillField selector="{{StorefrontCustomerSignInFormSection.emailField}}" userInput="$$customer.email$$" stepKey="fillEmail2"/> - <fillField selector="{{StorefrontCustomerSignInFormSection.passwordField}}" userInput="$$customer.password$$INVALID" stepKey="fillPassword2" /> - <click selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}" stepKey="clickSignInAccountButton2"/> - <see selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." stepKey="seeErrorMessage2" /> - <dontSee selector="StorefrontCustomerSignInFormSection.captchaField" stepKey="dontSeeCaptchaInputField2"/> - - <fillField selector="{{StorefrontCustomerSignInFormSection.emailField}}" userInput="$$customer.email$$" stepKey="fillEmail3"/> - <fillField selector="{{StorefrontCustomerSignInFormSection.passwordField}}" userInput="$$customer.password$$INVALID" stepKey="fillPassword3" /> - <click selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}" stepKey="clickSignInAccountButton3"/> - <see selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." stepKey="seeErrorMessage3" /> - - <!-- Check captcha visibility on login page --> - <waitForElementVisible selector="{{StorefrontCustomerSignInFormSection.captchaField}}" stepKey="seeCaptchaField"/> - <waitForElementVisible selector="{{StorefrontCustomerSignInFormSection.captchaImg}}" stepKey="seeCaptchaImage"/> - <waitForElementVisible selector="{{StorefrontCustomerSignInFormSection.captchaReload}}" stepKey="seeCaptchaReloadButton"/> - - <!-- Submit form with incorrect captcha --> - <fillField selector="{{StorefrontCustomerSignInFormSection.emailField}}" userInput="$$customer.email$$" stepKey="fillEmail4"/> - <fillField selector="{{StorefrontCustomerSignInFormSection.passwordField}}" userInput="$$customer.password$$INVALID" stepKey="fillPassword4" /> - <fillField selector="{{StorefrontCustomerSignInFormSection.captchaField}}" userInput="InvalidCaptcha" stepKey="fillCaptcha" /> - <click selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}" stepKey="clickSignInAccountButton4"/> - <see userInput="Incorrect CAPTCHA" selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="verifyMessage4"/> - </test> -</tests> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnCustomerLoginTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnCustomerLoginTest.xml new file mode 100644 index 0000000000000..ea63037b0551d --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnCustomerLoginTest.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="StorefrontCaptchaOnCustomerLoginTest"> + <annotations> + <features value="Captcha"/> + <stories value="Login with Customer Account + Captcha"/> + <title value="Captcha customer login page test"/> + <description value="Check CAPTCHA on Storefront Login Page."/> + <severity value="AVERAGE"/> + <testCaseId value="MC-14010" /> + <group value="captcha"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaLength3ConfigData.path}} {{StorefrontCustomerCaptchaLength3ConfigData.value}}" stepKey="setCaptchaLength" /> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaSymbols1ConfigData.path}} {{StorefrontCustomerCaptchaSymbols1ConfigData.value}}" stepKey="setCaptchaSymbols" /> + <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> + <createData entity="Simple_US_Customer" stepKey="customer"/> + </before> + <after> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaDefaultLengthConfigData.path}} {{StorefrontCustomerCaptchaDefaultLengthConfigData.value}}" stepKey="setDefaultCaptchaLength" /> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaDefaultSymbolsConfigData.path}} {{StorefrontCustomerCaptchaDefaultSymbolsConfigData.value}}" stepKey="setDefaultCaptchaSymbols" /> + <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + </after> + + <!-- Open storefront login form --> + <actionGroup ref="StorefrontOpenCustomerLoginPageActionGroup" stepKey="goToSignInPage" /> + + <!-- Login with wrong credentials 3 times --> + <actionGroup ref="StorefrontFillCustomerLoginFormActionGroup" stepKey="fillLoginFormFirstAttempt"> + <argument name="customer" value="Colorado_US_Customer" /> + </actionGroup> + <actionGroup ref="StorefrontClickSignOnCustomerLoginFormActionGroup" stepKey="clickSignInAccountButtonFirstAttempt" /> + <actionGroup ref="AssertMessageCustomerLoginActionGroup" stepKey="seeErrorMessageAfterFirstAttempt" /> + <actionGroup ref="AssertCaptchaNotVisibleOnCustomerLoginFormActionGroup" stepKey="dontSeeCaptchaAfterFirstAttempt" /> + + <actionGroup ref="StorefrontFillCustomerLoginFormActionGroup" stepKey="fillLoginFormSecondAttempt"> + <argument name="customer" value="Colorado_US_Customer" /> + </actionGroup> + <actionGroup ref="StorefrontClickSignOnCustomerLoginFormActionGroup" stepKey="clickSignInAccountButtonSecondAttempt" /> + <actionGroup ref="AssertMessageCustomerLoginActionGroup" stepKey="seeErrorMessageAfterSecondAttempt" /> + <actionGroup ref="AssertCaptchaNotVisibleOnCustomerLoginFormActionGroup" stepKey="dontSeeCaptchaAfterSecondAttempt" /> + + <actionGroup ref="StorefrontFillCustomerLoginFormActionGroup" stepKey="fillLoginFormThirdAttempt"> + <argument name="customer" value="Colorado_US_Customer" /> + </actionGroup> + <actionGroup ref="StorefrontClickSignOnCustomerLoginFormActionGroup" stepKey="clickSignInAccountButtonThirdAttempt" /> + <actionGroup ref="AssertMessageCustomerLoginActionGroup" stepKey="seeErrorMessageAfterThirdAttempt" /> + <actionGroup ref="AssertCaptchaVisibleOnCustomerLoginFormActionGroup" stepKey="dontSeeCaptchaAfterThirdAttempt" /> + + <!-- Submit form with incorrect captcha --> + <actionGroup ref="StorefrontFillCustomerLoginFormWithCaptchaActionGroup" stepKey="fillLoginFormCorrectAccountIncorrectCaptcha"> + <argument name="customer" value="$$customer$$" /> + <argument name="captcha" value="{{WrongCaptcha.value}}" /> + </actionGroup> + <actionGroup ref="StorefrontClickSignOnCustomerLoginFormActionGroup" stepKey="clickSignInAccountButtonCorrectAccountIncorrectCaptcha" /> + <actionGroup ref="AssertMessageCustomerLoginActionGroup" stepKey="seeErrorMessageAfterIncorrectCaptcha"> + <argument name="message" value="Incorrect CAPTCHA" /> + </actionGroup> + + <actionGroup ref="StorefrontFillCustomerLoginFormWithCaptchaActionGroup" stepKey="fillLoginFormCorrectAccountCorrectCaptcha"> + <argument name="customer" value="$$customer$$" /> + <argument name="captcha" value="{{PreconfiguredCaptcha.value}}" /> + </actionGroup> + <actionGroup ref="StorefrontClickSignOnCustomerLoginFormActionGroup" stepKey="clickSignInAccountButtonCorrectAccountCorrectCaptcha" /> + <actionGroup ref="AssertCustomerWelcomeMessageActionGroup" stepKey="assertCustomerLoggedIn"> + <argument name="customerFullName" value="$$customer.firstname$$ $$customer.lastname$$" /> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerLoggedInActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerLoggedInActionGroup.xml new file mode 100644 index 0000000000000..d9da950fe7115 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerLoggedInActionGroup.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="AssertCustomerWelcomeMessageActionGroup"> + <arguments> + <argument name="customerFullName" type="string" /> + </arguments> + <see userInput="Welcome, {{customerFullName}}!" selector="{{StorefrontPanelHeaderSection.welcomeMessage}}" stepKey="verifyMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertMessageCustomerLoginActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertMessageCustomerLoginActionGroup.xml new file mode 100644 index 0000000000000..6b88661985873 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertMessageCustomerLoginActionGroup.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="AssertMessageCustomerLoginActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." /> + <argument name="messageType" type="string" defaultValue="error" /> + </arguments> + <see userInput="{{message}}" selector="{{StorefrontCustomerLoginMessagesSection.messageByType(messageType)}}" stepKey="verifyMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontClickSignOnCustomerLoginFormActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontClickSignOnCustomerLoginFormActionGroup.xml new file mode 100644 index 0000000000000..9cd52b841fca4 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontClickSignOnCustomerLoginFormActionGroup.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="StorefrontClickSignOnCustomerLoginFormActionGroup"> + <click stepKey="clickSignInButton" selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}" /> + <waitForPageLoad stepKey="waitForCustomerSignIn" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillCustomerLoginFormActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillCustomerLoginFormActionGroup.xml new file mode 100644 index 0000000000000..22883ada7c2b1 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillCustomerLoginFormActionGroup.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="StorefrontFillCustomerLoginFormActionGroup"> + <arguments> + <argument name="customer" type="entity" /> + </arguments> + + <fillField userInput="{{customer.email}}" selector="{{StorefrontCustomerSignInFormSection.emailField}}" stepKey="fillEmail"/> + <fillField userInput="{{customer.password}}" selector="{{StorefrontCustomerSignInFormSection.passwordField}}" stepKey="fillPassword"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerLoginPageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerLoginPageActionGroup.xml new file mode 100644 index 0000000000000..0a5c72265528a --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerLoginPageActionGroup.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="StorefrontOpenCustomerLoginPageActionGroup"> + <amOnPage url="{{StorefrontCustomerSignInPage.url}}" stepKey="amOnSignInPage"/> + <waitForPageLoad stepKey="waitForPageLoaded"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerLoginMessagesSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerLoginMessagesSection.xml index 078021db062cc..85443e37a6f72 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerLoginMessagesSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerLoginMessagesSection.xml @@ -11,5 +11,6 @@ <section name="StorefrontCustomerLoginMessagesSection"> <element name="successMessage" type="text" selector=".message-success"/> <element name="errorMessage" type="text" selector=".message-error"/> + <element name="messageByType" type="block" selector="#maincontent .message-{{messageType}}" parameterized="true" /> </section> </sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml index a6f41fb63415c..7bc057b8be7b7 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml @@ -12,10 +12,7 @@ <element name="emailField" type="input" selector="#email"/> <element name="passwordField" type="input" selector="#pass"/> <element name="signInAccountButton" type="button" selector="#send2" timeout="30"/> - <element name="forgotPasswordLink" type="link" selector=".action.remind" timeout="10"/> - <element name="captchaField" type="input" selector="#captcha_user_login"/> - <element name="captchaImg" type="block" selector=".captcha-img"/> - <element name="captchaReload" type="block" selector=".captcha-reload"/> + <element name="forgotPasswordLink" type="button" selector=".action.remind" timeout="10"/> </section> <section name="StorefrontCustomerSignInPopupFormSection"> <element name="errorMessage" type="input" selector="[data-ui-id='checkout-cart-validationmessages-message-error']"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml index 4d7572aedc59b..dab298f6b416b 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml @@ -9,7 +9,10 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontPanelHeaderSection"> + <!-- Element name="WelcomeMessage" Deprecated due to incorrect naming convention please use name="welcomeMessage" --> <element name="WelcomeMessage" type="text" selector=".greet.welcome span"/> + + <element name="welcomeMessage" type="text" selector="header>.panel .greet.welcome" /> <element name="createAnAccountLink" type="select" selector="//div[@class='panel wrapper']//li/a[contains(.,'Create an Account')]" timeout="30"/> <element name="notYouLink" type="button" selector=".greet.welcome span a"/> <element name="customerWelcome" type="text" selector=".panel.header .customer-welcome"/> From fe953d687bbb9abb0edb8a4c4a2468ff817a60c8 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Tue, 2 Apr 2019 12:59:21 -0500 Subject: [PATCH 328/603] 229: [GraphQL caching] Add support for queries via HTTP GET --- .../GraphQl/Config/GraphQlReaderTest.php | 3 +- .../Controller/GraphQlControllerTest.php | 28 ------------------- 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php index 10a6b9d8caae4..59f9ad4c00832 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php @@ -185,7 +185,8 @@ enumValues(includeDeprecated: true) { $request->setHeaders($headers); $response = $this->graphQlController->dispatch($request); $output = $this->jsonSerializer->unserialize($response->getContent()); - $expectedOutput = require __DIR__ . '/../_files/schema_response_sdl_description.php'; + $expectationFile = __DIR__ . '/../_files/schema_response_sdl_description.php'; + $expectedOutput = require $expectationFile; $schemaResponseFields = $output['data']['__schema']['types']; $schemaResponseFieldsFirstHalf = array_slice($schemaResponseFields, 0, 25); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php index a83e644c6e171..0f7dfa97e8e2e 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php @@ -153,34 +153,6 @@ public function testDispatchWithGet() : void $this->assertEquals($output['data']['products']['items'][0]['name'], $product->getName()); } - /** - * Test mutation over GET returns error - */ - public function testMutationWithHttpGet() - { - $mutation = <<<MUTATION -mutation { - testItem(id: 3) { - item_id, - name, - integer_list - } -} -MUTATION; - - $request = $this->objectManager->get(Http::class); - $request->setPathInfo('/graphql'); - $request->setMethod('GET'); - //Http::isSafeMethod() checks $_SERVER which will be set on real HTTP request - $_SERVER['REQUEST_METHOD'] = 'GET'; - $request->setQueryValue('query', $mutation); - $response = $this->graphql->dispatch($request); - $output = $this->jsonSerializer->unserialize($response->getContent()); - $this->assertArrayHasKey('errors', $output); - $errorMessage = $output['errors'][0]['message']; - $this->assertEquals('Mutation requests allowed only for POST requests', $errorMessage); - } - /** Test request is dispatched and response generated when using GET request with parameterized query string * * @return void From b3402d7a4ed4b9a35567a25170fed956bf1316b2 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Tue, 2 Apr 2019 14:49:24 -0500 Subject: [PATCH 329/603] 229: [GraphQL caching] Add support for queries via HTTP GET --- .../Magento/Framework/GraphQl/Config/GraphQlReaderTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php index 59f9ad4c00832..6db1772458bef 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php @@ -185,8 +185,8 @@ enumValues(includeDeprecated: true) { $request->setHeaders($headers); $response = $this->graphQlController->dispatch($request); $output = $this->jsonSerializer->unserialize($response->getContent()); - $expectationFile = __DIR__ . '/../_files/schema_response_sdl_description.php'; - $expectedOutput = require $expectationFile; + //phpcs:ignore Magento2.Security.IncludeFile.FoundIncludeFile + $expectedOutput = require __DIR__ . '/../_files/schema_response_sdl_description.php'; $schemaResponseFields = $output['data']['__schema']['types']; $schemaResponseFieldsFirstHalf = array_slice($schemaResponseFields, 0, 25); From d193913c855ff381a48060e988b675e6ae0f40d6 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Tue, 2 Apr 2019 15:39:54 -0500 Subject: [PATCH 330/603] 229: [GraphQL caching] Add support for queries via HTTP GET --- .../Magento/TestFramework/TestCase/GraphQl/Client.php | 5 +++++ .../Magento/TestFramework/TestCase/GraphQlAbstract.php | 1 + .../Framework/GraphQl/Config/GraphQlReaderTest.php | 4 +++- .../Magento/GraphQl/Controller/GraphQlControllerTest.php | 9 +-------- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php index 6ace9b557ff9f..a5b16f454b041 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php @@ -66,12 +66,14 @@ public function postQuery(string $query, array $variables = [], string $operatio $responseBodyArray = $this->json->jsonDecode($responseBody); if (!is_array($responseBodyArray)) { + //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Unknown GraphQL response body: ' . json_encode($responseBodyArray)); } $this->processErrors($responseBodyArray); if (!isset($responseBodyArray['data'])) { + //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Unknown GraphQL response body: ' . json_encode($responseBodyArray)); } else { return $responseBodyArray['data']; @@ -101,12 +103,14 @@ public function getQuery(string $query, array $variables = [], string $operation $responseBodyArray = $this->json->jsonDecode($responseBody); if (!is_array($responseBodyArray)) { + //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Unknown GraphQL response body: ' . json_encode($responseBodyArray)); } $this->processErrors($responseBodyArray); if (!isset($responseBodyArray['data'])) { + //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Unknown GraphQL response body: ' . json_encode($responseBodyArray)); } else { return $responseBodyArray['data']; @@ -142,6 +146,7 @@ private function processErrors($responseBodyArray) $responseBodyArray ); } + //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('GraphQL responded with an unknown error: ' . json_encode($responseBodyArray)); } } diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php index d1a6356d78fba..021bfa35669fb 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php @@ -61,6 +61,7 @@ public function graphQlQuery( $this->composeHeaders($headers) ); } else { + //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception("Unsupported request type"); } diff --git a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php index 6db1772458bef..b96b04eb4e671 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php @@ -45,7 +45,9 @@ protected function setUp() \Magento\Framework\Config\FileResolverInterface::class )->disableOriginalConstructor()->getMock(); $fileList = [ + //phpcs:ignore Magento2.Functions.DiscouragedFunction file_get_contents(__DIR__ . '/../_files/schemaA.graphqls'), + //phpcs:ignore Magento2.Functions.DiscouragedFunction file_get_contents(__DIR__ . '/../_files/schemaB.graphqls') ]; $fileResolverMock->expects($this->any())->method('get')->will($this->returnValue($fileList)); @@ -185,7 +187,7 @@ enumValues(includeDeprecated: true) { $request->setHeaders($headers); $response = $this->graphQlController->dispatch($request); $output = $this->jsonSerializer->unserialize($response->getContent()); - //phpcs:ignore Magento2.Security.IncludeFile.FoundIncludeFile + //phpcs:ignore Magento2.Security.IncludeFile $expectedOutput = require __DIR__ . '/../_files/schema_response_sdl_description.php'; $schemaResponseFields = $output['data']['__schema']['types']; diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php index 0f7dfa97e8e2e..8a36767d6de2b 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php @@ -38,6 +38,7 @@ class GraphQlControllerTest extends \Magento\TestFramework\Indexer\TestCase /** @var MetadataPool */ private $metadataPool; + //phpcs:ignore Magento2.Functions.StaticFunction public static function setUpBeforeClass() { $db = Bootstrap::getInstance()->getBootstrap() @@ -265,12 +266,4 @@ public function testError() : void } } } - - /** - * teardown - */ - public function tearDown() - { - parent::tearDown(); - } } From 92b0e8b1247c2e039046bfc33a6c5930ecf67bbe Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Tue, 2 Apr 2019 15:46:57 -0500 Subject: [PATCH 331/603] MAGETWO-98831: The SKU was not found in the catalog --- .../Adminhtml/Order/Create/Search/Grid.php | 29 +++++++++- .../Grid/DataProvider/ProductCollection.php | 56 +++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid/DataProvider/ProductCollection.php diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid.php index 4bd2227d4bb1e..5b7c1dee65c39 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid.php @@ -5,6 +5,10 @@ */ namespace Magento\Sales\Block\Adminhtml\Order\Create\Search; +use Magento\Sales\Block\Adminhtml\Order\Create\Search\Grid\DataProvider\ProductCollection + as ProductCollectionDataProvider; +use Magento\Framework\App\ObjectManager; + /** * Adminhtml sales order create search products block * @@ -42,6 +46,11 @@ class Grid extends \Magento\Backend\Block\Widget\Grid\Extended */ protected $_productFactory; + /** + * @var ProductCollectionDataProvider $productCollectionProvider + */ + private $productCollectionProvider; + /** * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Backend\Helper\Data $backendHelper @@ -50,6 +59,7 @@ class Grid extends \Magento\Backend\Block\Widget\Grid\Extended * @param \Magento\Backend\Model\Session\Quote $sessionQuote * @param \Magento\Sales\Model\Config $salesConfig * @param array $data + * @param ProductCollectionDataProvider|null $productCollectionProvider */ public function __construct( \Magento\Backend\Block\Template\Context $context, @@ -58,12 +68,15 @@ public function __construct( \Magento\Catalog\Model\Config $catalogConfig, \Magento\Backend\Model\Session\Quote $sessionQuote, \Magento\Sales\Model\Config $salesConfig, - array $data = [] + array $data = [], + ProductCollectionDataProvider $productCollectionProvider = null ) { $this->_productFactory = $productFactory; $this->_catalogConfig = $catalogConfig; $this->_sessionQuote = $sessionQuote; $this->_salesConfig = $salesConfig; + $this->productCollectionProvider = $productCollectionProvider + ?: ObjectManager::getInstance()->get(ProductCollectionDataProvider::class); parent::__construct($context, $backendHelper, $data); } @@ -140,8 +153,21 @@ protected function _addColumnFilterToCollection($column) */ protected function _prepareCollection() { + $attributes = $this->_catalogConfig->getProductAttributes(); + $store = $this->getStore(); + /* @var $collection \Magento\Catalog\Model\ResourceModel\Product\Collection */ + $collection = $this->productCollectionProvider->getCollectionForStore($store); + $collection->addAttributeToSelect( + $attributes + ); + $collection->addAttributeToFilter( + 'type_id', + $this->_salesConfig->getAvailableProductTypes() + ); + + /* $collection = $this->_productFactory->create()->getCollection(); $collection->setStore( $this->getStore() @@ -155,6 +181,7 @@ protected function _prepareCollection() )->addAttributeToSelect( 'gift_message_available' ); + */ $this->setCollection($collection); return parent::_prepareCollection(); diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid/DataProvider/ProductCollection.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid/DataProvider/ProductCollection.php new file mode 100644 index 0000000000000..61f30de3a1c51 --- /dev/null +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid/DataProvider/ProductCollection.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\Block\Adminhtml\Order\Create\Search\Grid\DataProvider; + +use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory; +use Magento\Catalog\Model\ResourceModel\Product\Collection; +use Magento\Store\Model\Store; + +/** + * Prepares product collection for the grid + */ +class ProductCollection +{ + /** + * @var ProductCollectionFactory + */ + private $collectionFactory; + + /** + * @param ProductCollectionFactory $collectionFactory + */ + public function __construct( + ProductCollectionFactory $collectionFactory + ) { + $this->collectionFactory = $collectionFactory; + } + + /** + * Provide products collection filtered with store + * + * @param Store $store + * @return Collection + */ + public function getCollectionForStore(Store $store):Collection + { + /** @var Collection $collection */ + $collection = $this->collectionFactory->create(); + + $collection->setStore($store); + $collection->addAttributeToSelect( + 'gift_message_available' + ); + $collection->addAttributeToSelect( + 'sku' + ); + $collection->addStoreFilter(); + + return $collection; + } +} + From 6b3d4d688be5e747410e56fdda1f277767234205 Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Tue, 2 Apr 2019 16:02:56 -0500 Subject: [PATCH 332/603] MAGETWO-99022: Braintree Displaying Incorrect Ship-To Name --- .../Model/Paypal/Helper/QuoteUpdater.php | 28 +++++++++++++++++-- .../Model/Paypal/Helper/QuoteUpdaterTest.php | 6 ++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php b/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php index aa23fa767d1ed..11c51e07f1dd9 100644 --- a/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php +++ b/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php @@ -123,8 +123,8 @@ private function updateShippingAddress(Quote $quote, array $details) { $shippingAddress = $quote->getShippingAddress(); - $shippingAddress->setLastname($details['lastName']); - $shippingAddress->setFirstname($details['firstName']); + $shippingAddress->setLastname($this->getShippingRecipientLastName($details)); + $shippingAddress->setFirstname($this->getShippingRecipientFirstName($details)); $shippingAddress->setEmail($details['email']); $shippingAddress->setCollectShippingRates(true); @@ -188,4 +188,28 @@ private function updateAddressData(Address $address, array $addressData) $address->setSameAsBilling(false); $address->setCustomerAddressId(null); } + + /** + * Returns shipping recipient first name. + * + * @param array $details + * @return string + */ + private function getShippingRecipientFirstName(array $details) + { + return explode(' ', $details['shippingAddress']['recipientName'], 2)[0] + ?? $details['firstName']; + } + + /** + * Returns shipping recipient last name. + * + * @param array $details + * @return string + */ + private function getShippingRecipientLastName(array $details) + { + return explode(' ', $details['shippingAddress']['recipientName'], 2)[1] + ?? $details['lastName']; + } } diff --git a/app/code/Magento/Braintree/Test/Unit/Model/Paypal/Helper/QuoteUpdaterTest.php b/app/code/Magento/Braintree/Test/Unit/Model/Paypal/Helper/QuoteUpdaterTest.php index a2b5380d2884b..c2678d1c78437 100644 --- a/app/code/Magento/Braintree/Test/Unit/Model/Paypal/Helper/QuoteUpdaterTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Model/Paypal/Helper/QuoteUpdaterTest.php @@ -165,7 +165,7 @@ private function getDetails(): array 'region' => 'IL', 'postalCode' => '60618', 'countryCodeAlpha2' => 'US', - 'recipientName' => 'John Doe', + 'recipientName' => 'Jane Smith', ], 'billingAddress' => [ 'streetAddress' => '123 Billing Street', @@ -186,9 +186,9 @@ private function getDetails(): array private function updateShippingAddressStep(array $details): void { $this->shippingAddress->method('setLastname') - ->with($details['lastName']); + ->with('Smith'); $this->shippingAddress->method('setFirstname') - ->with($details['firstName']); + ->with('Jane'); $this->shippingAddress->method('setEmail') ->with($details['email']); $this->shippingAddress->method('setCollectShippingRates') From c62b949ddc12cd714ff541f2e6fc11a3e3804751 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Tue, 2 Apr 2019 16:03:58 -0500 Subject: [PATCH 333/603] 229: [GraphQL caching] Add support for queries via HTTP GET - This reverts commit d193913c855ff381a48060e988b675e6ae0f40d6. --- .../Magento/TestFramework/TestCase/GraphQl/Client.php | 5 ----- .../Magento/TestFramework/TestCase/GraphQlAbstract.php | 1 - .../Framework/GraphQl/Config/GraphQlReaderTest.php | 3 --- .../Magento/GraphQl/Controller/GraphQlControllerTest.php | 9 ++++++++- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php index a5b16f454b041..6ace9b557ff9f 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php @@ -66,14 +66,12 @@ public function postQuery(string $query, array $variables = [], string $operatio $responseBodyArray = $this->json->jsonDecode($responseBody); if (!is_array($responseBodyArray)) { - //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Unknown GraphQL response body: ' . json_encode($responseBodyArray)); } $this->processErrors($responseBodyArray); if (!isset($responseBodyArray['data'])) { - //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Unknown GraphQL response body: ' . json_encode($responseBodyArray)); } else { return $responseBodyArray['data']; @@ -103,14 +101,12 @@ public function getQuery(string $query, array $variables = [], string $operation $responseBodyArray = $this->json->jsonDecode($responseBody); if (!is_array($responseBodyArray)) { - //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Unknown GraphQL response body: ' . json_encode($responseBodyArray)); } $this->processErrors($responseBodyArray); if (!isset($responseBodyArray['data'])) { - //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Unknown GraphQL response body: ' . json_encode($responseBodyArray)); } else { return $responseBodyArray['data']; @@ -146,7 +142,6 @@ private function processErrors($responseBodyArray) $responseBodyArray ); } - //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('GraphQL responded with an unknown error: ' . json_encode($responseBodyArray)); } } diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php index 021bfa35669fb..d1a6356d78fba 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php @@ -61,7 +61,6 @@ public function graphQlQuery( $this->composeHeaders($headers) ); } else { - //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception("Unsupported request type"); } diff --git a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php index b96b04eb4e671..10a6b9d8caae4 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/Config/GraphQlReaderTest.php @@ -45,9 +45,7 @@ protected function setUp() \Magento\Framework\Config\FileResolverInterface::class )->disableOriginalConstructor()->getMock(); $fileList = [ - //phpcs:ignore Magento2.Functions.DiscouragedFunction file_get_contents(__DIR__ . '/../_files/schemaA.graphqls'), - //phpcs:ignore Magento2.Functions.DiscouragedFunction file_get_contents(__DIR__ . '/../_files/schemaB.graphqls') ]; $fileResolverMock->expects($this->any())->method('get')->will($this->returnValue($fileList)); @@ -187,7 +185,6 @@ enumValues(includeDeprecated: true) { $request->setHeaders($headers); $response = $this->graphQlController->dispatch($request); $output = $this->jsonSerializer->unserialize($response->getContent()); - //phpcs:ignore Magento2.Security.IncludeFile $expectedOutput = require __DIR__ . '/../_files/schema_response_sdl_description.php'; $schemaResponseFields = $output['data']['__schema']['types']; diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php index 8a36767d6de2b..0f7dfa97e8e2e 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php @@ -38,7 +38,6 @@ class GraphQlControllerTest extends \Magento\TestFramework\Indexer\TestCase /** @var MetadataPool */ private $metadataPool; - //phpcs:ignore Magento2.Functions.StaticFunction public static function setUpBeforeClass() { $db = Bootstrap::getInstance()->getBootstrap() @@ -266,4 +265,12 @@ public function testError() : void } } } + + /** + * teardown + */ + public function tearDown() + { + parent::tearDown(); + } } From 4ebea9626a0226454e1a5e4eb0afac02bdd27323 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 2 Apr 2019 20:57:39 -0500 Subject: [PATCH 334/603] GraphQL-481: [Test Coverage] 'RemoveCouponFromCart' functionality --- .../Model/Resolver/AppliedCoupon.php | 19 +- .../Model/Resolver/RemoveCouponFromCart.php | 6 +- .../Customer/RemoveCouponFromCartTest.php | 361 +++--------------- .../Quote/Guest/RemoveCouponFromCartTest.php | 211 ++-------- .../discount_10percent_generalusers.php | 2 +- .../GraphQl/Quote/_files/apply_coupon.php | 22 ++ .../Quote/_files/apply_coupon_rollback.php | 22 ++ 7 files changed, 170 insertions(+), 473 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/apply_coupon.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/apply_coupon_rollback.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/AppliedCoupon.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/AppliedCoupon.php index ca69b763929be..8251089abcd60 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/AppliedCoupon.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/AppliedCoupon.php @@ -11,12 +11,27 @@ use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; +use Magento\Quote\Api\CouponManagementInterface; /** * @inheritdoc */ class AppliedCoupon implements ResolverInterface { + /** + * @var CouponManagementInterface + */ + private $couponManagement; + + /** + * @param CouponManagementInterface $couponManagement + */ + public function __construct( + CouponManagementInterface $couponManagement + ) { + $this->couponManagement = $couponManagement; + } + /** * @inheritdoc */ @@ -26,9 +41,9 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value throw new LocalizedException(__('"model" value should be specified')); } $cart = $value['model']; + $cartId = $cart->getId(); - $appliedCoupon = $cart->getCouponCode(); - + $appliedCoupon = $this->couponManagement->get($cartId); return $appliedCoupon ? ['code' => $appliedCoupon] : null; } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php index 5a708ceaedc28..f81ea3020d3d0 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php @@ -62,7 +62,11 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value try { $this->couponManagement->remove($cartId); } catch (NoSuchEntityException $e) { - throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); + $message = $e->getMessage(); + if (preg_match('/The "\d+" Cart doesn\'t contain products/', $message)) { + $message = 'Cart does not contain products'; + } + throw new GraphQlNoSuchEntityException(__($message), $e); } catch (CouldNotDeleteException $e) { throw new LocalizedException(__($e->getMessage()), $e); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveCouponFromCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveCouponFromCartTest.php index b228d315f8890..689b360f724a7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveCouponFromCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveCouponFromCartTest.php @@ -7,92 +7,50 @@ namespace Magento\GraphQl\Quote\Customer; -use Magento\Framework\Exception\AuthenticationException; -use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Exception\NoSuchEntityException; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\Integration\Api\CustomerTokenServiceInterface; -use Magento\Quote\Model\Quote; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; -use Magento\SalesRule\Api\CouponRepositoryInterface; -use Magento\SalesRule\Model\Coupon; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; /** - * Check removing of the coupon from customer quotes + * Check removing of the coupon from customer cart */ class RemoveCouponFromCartTest extends GraphQlAbstract { - /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var Quote - */ - private $quote; - - /** - * @var QuoteIdToMaskedQuoteIdInterface - */ - private $quoteIdToMaskedId; - /** * @var CustomerTokenServiceInterface */ private $customerTokenService; /** - * @var CouponRepositoryInterface + * @var GetMaskedQuoteIdByReservedOrderId */ - private $couponRepository; + private $getMaskedQuoteIdByReservedOrderId; /** - * @var Coupon + * @inheritdoc */ - private $coupon; - protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->create(QuoteResource::class); - $this->quote = $objectManager->create(Quote::class); - $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); - $this->couponRepository = $objectManager->get(CouponRepositoryInterface::class); - $this->coupon = $objectManager->create(Coupon::class); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent_generalusers.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/apply_coupon.php */ public function testRemoveCouponFromCart() { - $couponCode = '2?ds5!2d'; - - /* Assign the quote to the customer */ - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - /* Apply coupon to the customer quote */ - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query, [], '', $queryHeaders); - - /* Remove coupon from the quote */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); - $response = $this->graphQlQuery($query, [], '', $queryHeaders); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('removeCouponFromCart', $response); self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); @@ -100,276 +58,92 @@ public function testRemoveCouponFromCart() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ - public function testRemoveCouponFromCartTwice() + public function testRemoveCouponFromNonExistentCart() { - $couponCode = '2?ds5!2d'; - - /* Assign the quote to the customer */ - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); - /* Apply coupon to the customer quote */ - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query, [], '', $queryHeaders); - - /* Remove coupon from the quote */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); - $response = $this->graphQlQuery($query, [], '', $queryHeaders); - - self::assertArrayHasKey('removeCouponFromCart', $response); - self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); - - /* Remove coupon from the quote the second time */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); - $response = $this->graphQlQuery($query, [], '', $queryHeaders); - - self::assertArrayHasKey('removeCouponFromCart', $response); - self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - */ - public function testRemoveCouponFromCartWithNoCouponApplied() - { - /* Assign the quote to the customer */ - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - - /* Remove coupon from the quote */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $response = $this->graphQlQuery($query, [], '', $queryHeaders); - - self::assertArrayHasKey('removeCouponFromCart', $response); - self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); - } - - /** - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @expectedException \Exception + * @expectedExceptionMessage Cart does not contain products */ public function testRemoveCouponFromEmptyCart() { - /* Assign the empty quote to the customer */ - $this->quoteResource->load( - $this->quote, - 'test_order_1', - 'reserved_order_id' - ); - $quoteId = (int)$this->quote->getId(); - $maskedQuoteId = $this->quoteIdToMaskedId->execute($quoteId); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - - /* Remove coupon from the empty quote */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - - $this->expectExceptionMessage("The \"$quoteId\" Cart doesn't contain products"); - $this->graphQlQuery($query, [], '', $queryHeaders); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ - public function testRemoveCouponFromCartWithoutItems() + public function testRemoveCouponFromCartIfCouponWasNotSet() { - $couponCode = '2?ds5!2d'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - /* Assign the quote to the customer */ - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - - /* Apply coupon to the customer quote */ - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query, [], '', $queryHeaders); - - /* Clear the quote */ - $this->quote->removeAllItems(); - $this->quoteResource->save($this->quote); - - /* Remove coupon from the customer quote */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); - $response = $this->graphQlQuery($query, [], '', $queryHeaders); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('removeCouponFromCart', $response); self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); } /** - * @magentoApiDataFixture Magento/Customer/_files/two_customers.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php - */ - public function testRemoveCouponFromAnotherCustomerCart() - { - $couponCode = '2?ds5!2d'; - - /* Assign the quote to the customer */ - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - - /* Apply coupon to the first customer quote */ - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $this->graphQlQuery($query, [], '', $queryHeaders); - - /* Remove coupon from the quote from the second customer */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); - $queryHeaders = $this->prepareAuthorizationHeaders('customer_two@example.com', 'password'); - - $this->expectExceptionMessage("The current user cannot perform operations on cart \"$maskedQuoteId\""); - $this->graphQlQuery($query, [], '', $queryHeaders); - } - - /** + * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/apply_coupon.php */ public function testRemoveCouponFromGuestCart() { - $couponCode = '2?ds5!2d'; - - /* Apply coupon to the guest quote */ - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query); - - /* Remove coupon from quote */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - - $this->expectExceptionMessage("The current user cannot perform operations on cart \"$maskedQuoteId\""); - $this->graphQlQuery($query, [], '', $queryHeaders); - } - - /** - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php - */ - public function testRemoveNonExistentCouponFromCart() - { - $couponCode = '2?ds5!2d'; - - /* Assign the quote to the customer */ - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - - /* Apply coupon to the customer quote */ - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $this->graphQlQuery($query, [], '', $queryHeaders); - - /* Remove the coupon */ - $this->removeCoupon($couponCode); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); - /* Remove the non-existent coupon from the quote */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); - - $response = $this->graphQlQuery($query, [], '', $queryHeaders); - - self::assertArrayHasKey('removeCouponFromCart', $response); - self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); + self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } /** - * Remove the given coupon code from the database - * - * @param string $couponCode - * @throws LocalizedException - * @throws NoSuchEntityException + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent_generalusers.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/apply_coupon.php */ - private function removeCoupon(string $couponCode): void - { - $this->coupon->loadByCode($couponCode); - $couponId = $this->coupon->getCouponId(); - - if ($couponId) { - $this->couponRepository->deleteById($couponId); - } - } - - /** - * Retrieve customer authorization headers - * - * @param string $email - * @param string $password - * @return array - * @throws AuthenticationException - */ - private function prepareAuthorizationHeaders(string $email, string $password): array + public function testRemoveCouponFromAnotherCustomerCart() { - $customerToken = $this->customerTokenService->createCustomerAccessToken($email, $password); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); - return ['Authorization' => 'Bearer ' . $customerToken]; + self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); + $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer3@search.example.com')); } /** - * Retrieve add coupon GraphQL query - * * @param string $maskedQuoteId - * @param string $couponCode * @return string */ - private function prepareAddCouponRequestQuery(string $maskedQuoteId, string $couponCode): string + private function getQuery(string $maskedQuoteId): string { return <<<QUERY mutation { - applyCouponToCart(input: {cart_id: "$maskedQuoteId", coupon_code: "$couponCode"}) { + removeCouponFromCart(input: {cart_id: "$maskedQuoteId"}) { cart { applied_coupon { code @@ -377,28 +151,19 @@ private function prepareAddCouponRequestQuery(string $maskedQuoteId, string $cou } } } + QUERY; } /** - * Retrieve remove coupon GraphQL query - * - * @param string $maskedQuoteId - * @return string + * @param string $username + * @param string $password + * @return array */ - private function prepareRemoveCouponRequestQuery(string $maskedQuoteId): string + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array { - return <<<QUERY -mutation { - removeCouponFromCart(input: {cart_id: "$maskedQuoteId"}) { - cart { - applied_coupon { - code - } - } - } -} - -QUERY; + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveCouponFromCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveCouponFromCartTest.php index c5929795b534a..a17ef545eba88 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveCouponFromCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveCouponFromCartTest.php @@ -7,78 +7,41 @@ namespace Magento\GraphQl\Quote\Guest; -use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Quote\Model\Quote; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; -use Magento\SalesRule\Api\CouponRepositoryInterface; -use Magento\SalesRule\Model\Coupon; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; /** - * Test for getting cart information + * Check removing of the coupon from guest cart */ class RemoveCouponFromCartTest extends GraphQlAbstract { /** - * @var QuoteResource + * @var GetMaskedQuoteIdByReservedOrderId */ - private $quoteResource; + private $getMaskedQuoteIdByReservedOrderId; /** - * @var Quote + * @inheritdoc */ - private $quote; - - /** - * @var QuoteIdToMaskedQuoteIdInterface - */ - private $quoteIdToMaskedId; - - /** - * @var CouponRepositoryInterface - */ - private $couponRepository; - - /** - * @var Coupon - */ - private $coupon; - protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->create(QuoteResource::class); - $this->quote = $objectManager->create(Quote::class); - $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); - $this->couponRepository = $objectManager->get(CouponRepositoryInterface::class); - $this->coupon = $objectManager->create(Coupon::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/apply_coupon.php */ public function testRemoveCouponFromCart() { - $couponCode = '2?ds5!2d'; - - /* Apply coupon to the quote */ - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - /* Remove coupon from quote */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); + $query = $this->getQuery($maskedQuoteId); $response = $this->graphQlQuery($query); self::assertArrayHasKey('removeCouponFromCart', $response); @@ -86,84 +49,40 @@ public function testRemoveCouponFromCart() } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php - * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ - public function testRemoveCouponFromCustomerCart() - { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); - - self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query); - } - public function testRemoveCouponFromNonExistentCart() { - $maskedQuoteId = '1234000000099912'; + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); - /* Remove coupon from quote */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); - - self::expectExceptionMessage('Could not find a cart with ID "' . $maskedQuoteId. '"'); $this->graphQlQuery($query); } /** - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @expectedException \Exception + * @expectedExceptionMessage Cart does not contain products */ public function testRemoveCouponFromEmptyCart() { - $this->quoteResource->load( - $this->quote, - 'test_order_1', - 'reserved_order_id' - ); - $quoteId = (int)$this->quote->getId(); - $maskedQuoteId = $this->quoteIdToMaskedId->execute($quoteId); - - /* Remove coupon from the empty quote */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); - $this->expectExceptionMessage("The \"$quoteId\" Cart doesn't contain products"); $this->graphQlQuery($query); } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ - public function testRemoveCouponFromCartWithoutItems() + public function testRemoveCouponFromCartIfCouponWasNotSet() { - $couponCode = '2?ds5!2d'; - - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - - /* Apply coupon to the guest quote */ - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query); - - /* Clear the quote */ - $this->quote->removeAllItems(); - $this->quoteResource->save($this->quote); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - /* Remove coupon from the guest quote */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); + $query = $this->getQuery($maskedQuoteId); $response = $this->graphQlQuery($query); self::assertArrayHasKey('removeCouponFromCart', $response); @@ -171,82 +90,32 @@ public function testRemoveCouponFromCartWithoutItems() } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent_generalusers.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/apply_coupon.php */ - public function testRemoveNonExistentCouponFromCart() + public function testRemoveCouponFromCustomerCart() { - $couponCode = '2?ds5!2d'; - - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); - /* Apply coupon to the guest quote */ - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); $this->graphQlQuery($query); - - /* Remove the coupon */ - $this->removeCoupon($couponCode); - - /* Remove the non-existent coupon from the quote */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); - - $response = $this->graphQlQuery($query); - - self::assertArrayHasKey('removeCouponFromCart', $response); - self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); - } - - /** - * Remove the given coupon code from the database - * - * @param string $couponCode - * @throws LocalizedException - * @throws NoSuchEntityException - */ - private function removeCoupon(string $couponCode): void - { - $this->coupon->loadByCode($couponCode); - $couponId = $this->coupon->getCouponId(); - - if ($couponId) { - $this->couponRepository->deleteById($couponId); - } - } - - /** - * @param string $maskedQuoteId - * @param string $couponCode - * @return string - */ - private function prepareAddCouponRequestQuery(string $maskedQuoteId, string $couponCode): string - { - return <<<QUERY -mutation { - applyCouponToCart(input: {cart_id: "$maskedQuoteId", coupon_code: "$couponCode"}) { - cart { - applied_coupon { - code - } - } - } -} -QUERY; } /** * @param string $maskedQuoteId * @return string */ - private function prepareRemoveCouponRequestQuery(string $maskedQuoteId): string + private function getQuery(string $maskedQuoteId): string { return <<<QUERY mutation { - removeCouponFromCart(input: {cart_id: "$maskedQuoteId"}) { + removeCouponFromCart(input: {cart_id: "{$maskedQuoteId}"}) { cart { applied_coupon { code diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_generalusers.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_generalusers.php index 507f6b755bcda..e66227a60e8f0 100644 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_generalusers.php +++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_generalusers.php @@ -21,7 +21,7 @@ ], 'customer_group_ids' => [1], 'coupon_type' => \Magento\SalesRule\Model\Rule::COUPON_TYPE_SPECIFIC, - 'coupon_code' => uniqid(), + 'coupon_code' => '2?ds5!2d', 'simple_action' => \Magento\SalesRule\Model\Rule::BY_PERCENT_ACTION, 'discount_amount' => 10, 'discount_step' => 1 diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/apply_coupon.php b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/apply_coupon.php new file mode 100644 index 0000000000000..c70efa9a12a5d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/apply_coupon.php @@ -0,0 +1,22 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Quote\Api\CouponManagementInterface; +use Magento\Quote\Model\QuoteFactory; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\TestFramework\Helper\Bootstrap; + +/** @var CouponManagementInterface $couponManagement */ +$couponManagement = Bootstrap::getObjectManager()->get(CouponManagementInterface::class); +/** @var QuoteFactory $quoteFactory */ +$quoteFactory = Bootstrap::getObjectManager()->get(QuoteFactory::class); +/** @var QuoteResource $quoteResource */ +$quoteResource = Bootstrap::getObjectManager()->get(QuoteResource::class); + +$quote = $quoteFactory->create(); +$quoteResource->load($quote, 'test_quote', 'reserved_order_id'); +$couponManagement->set($quote->getId(), '2?ds5!2d'); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/apply_coupon_rollback.php b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/apply_coupon_rollback.php new file mode 100644 index 0000000000000..5431c25b7df53 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/apply_coupon_rollback.php @@ -0,0 +1,22 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Quote\Api\CouponManagementInterface; +use Magento\Quote\Model\QuoteFactory; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\TestFramework\Helper\Bootstrap; + +/** @var CouponManagementInterface $couponManagement */ +$couponManagement = Bootstrap::getObjectManager()->get(CouponManagementInterface::class); +/** @var QuoteFactory $quoteFactory */ +$quoteFactory = Bootstrap::getObjectManager()->get(QuoteFactory::class); +/** @var QuoteResource $quoteResource */ +$quoteResource = Bootstrap::getObjectManager()->get(QuoteResource::class); + +$quote = $quoteFactory->create(); +$quoteResource->load($quote, 'test_quote', 'reserved_order_id'); +$couponManagement->remove($quote->getId()); From 5b0348830b27ab4c9fa1e86b8743c02c4f868b4c Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 2 Apr 2019 21:29:36 -0500 Subject: [PATCH 335/603] GraphQL-468: Resolve coupling between objects in `\Magento\QuoteGraphQl\Model\Cart\SetBillingAddressOnCart` --- .../CreateQuoteAddressByCustomerAddress.php | 71 ------------------- .../Model/Cart/QuoteAddressFactory.php | 25 +++++-- .../Model/Cart/SetBillingAddressOnCart.php | 43 +++++++---- .../Model/Cart/SetShippingAddressesOnCart.php | 15 ++-- 4 files changed, 52 insertions(+), 102 deletions(-) delete mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/CreateQuoteAddressByCustomerAddress.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateQuoteAddressByCustomerAddress.php b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateQuoteAddressByCustomerAddress.php deleted file mode 100644 index ba46f5621ee82..0000000000000 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateQuoteAddressByCustomerAddress.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\QuoteGraphQl\Model\Cart; - -use Magento\CustomerGraphQl\Model\Customer\Address\GetCustomerAddress; -use Magento\CustomerGraphQl\Model\Customer\GetCustomer; -use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; -use Magento\Quote\Model\Quote\Address; - -/** - * Creates a quote address based on given context, customer address ID and customer address - */ -class CreateQuoteAddressByCustomerAddress -{ - /** - * @var QuoteAddressFactory - */ - private $quoteAddressFactory; - - /** - * @var GetCustomer - */ - private $getCustomer; - - /** - * @var GetCustomerAddress - */ - private $getCustomerAddress; - - /** - * @param QuoteAddressFactory $quoteAddressFactory - * @param GetCustomer $getCustomer - * @param GetCustomerAddress $getCustomerAddress - */ - public function __construct( - QuoteAddressFactory $quoteAddressFactory, - GetCustomer $getCustomer, - GetCustomerAddress $getCustomerAddress - ) { - $this->quoteAddressFactory = $quoteAddressFactory; - $this->getCustomer = $getCustomer; - $this->getCustomerAddress = $getCustomerAddress; - } - - /** - * @param ContextInterface $context - * @param int|string|null $customerAddressId - * @param array|null $customerAddress - * - * @return Address - */ - public function execute( - ContextInterface $context, - $customerAddressId, - $customerAddress - ): Address { - if (null === $customerAddressId) { - return $this->quoteAddressFactory->createBasedOnInputData($customerAddress); - } - - $customer = $this->getCustomer->execute($context); - $customerAddress = $this->getCustomerAddress->execute((int)$customerAddressId, (int)$customer->getId()); - - return $this->quoteAddressFactory->createBasedOnCustomerAddress($customerAddress); - } -} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php index 76bdc74611131..582055bc6e13d 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php @@ -7,9 +7,11 @@ namespace Magento\QuoteGraphQl\Model\Cart; -use Magento\Customer\Api\Data\AddressInterface as CustomerAddress; +use Magento\CustomerGraphQl\Model\Customer\Address\GetCustomerAddress; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Quote\Model\Quote\Address as QuoteAddress; use Magento\Quote\Model\Quote\AddressFactory as BaseQuoteAddressFactory; @@ -23,13 +25,21 @@ class QuoteAddressFactory */ private $quoteAddressFactory; + /** + * @var GetCustomerAddress + */ + private $getCustomerAddress; + /** * @param BaseQuoteAddressFactory $quoteAddressFactory + * @param GetCustomerAddress $getCustomerAddress */ public function __construct( - BaseQuoteAddressFactory $quoteAddressFactory + BaseQuoteAddressFactory $quoteAddressFactory, + GetCustomerAddress $getCustomerAddress ) { $this->quoteAddressFactory = $quoteAddressFactory; + $this->getCustomerAddress = $getCustomerAddress; } /** @@ -48,14 +58,19 @@ public function createBasedOnInputData(array $addressInput): QuoteAddress } /** - * Create QuoteAddress based on CustomerAddress + * Create Quote Address based on Customer Address * - * @param CustomerAddress $customerAddress + * @param int $customerAddressId + * @param int $customerId * @return QuoteAddress * @throws GraphQlInputException + * @throws GraphQlAuthorizationException + * @throws GraphQlNoSuchEntityException */ - public function createBasedOnCustomerAddress(CustomerAddress $customerAddress): QuoteAddress + public function createBasedOnCustomerAddress(int $customerAddressId, int $customerId): QuoteAddress { + $customerAddress = $this->getCustomerAddress->execute((int)$customerAddressId, $customerId); + $quoteAddress = $this->quoteAddressFactory->create(); try { $quoteAddress->importCustomerAddressData($customerAddress); diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php index 65afbecb2c3f5..c2bac13c07067 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php @@ -7,6 +7,7 @@ namespace Magento\QuoteGraphQl\Model\Cart; +use Magento\CustomerGraphQl\Model\Customer\GetCustomer; use Magento\Framework\GraphQl\Exception\GraphQlAuthenticationException; use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; @@ -20,25 +21,33 @@ class SetBillingAddressOnCart { /** - * @var AssignBillingAddressToCart + * @var QuoteAddressFactory */ - private $assignBillingAddressToCart; + private $quoteAddressFactory; /** - * @var CreateQuoteAddressByCustomerAddress + * @var GetCustomer */ - private $createQuoteAddressByCustomerAddress; + private $getCustomer; + + /** + * @var AssignBillingAddressToCart + */ + private $assignBillingAddressToCart; /** + * @param QuoteAddressFactory $quoteAddressFactory + * @param GetCustomer $getCustomer * @param AssignBillingAddressToCart $assignBillingAddressToCart - * @param CreateQuoteAddressByCustomerAddress $createQuoteAddressByCustomerAddress */ public function __construct( - AssignBillingAddressToCart $assignBillingAddressToCart, - CreateQuoteAddressByCustomerAddress $createQuoteAddressByCustomerAddress + QuoteAddressFactory $quoteAddressFactory, + GetCustomer $getCustomer, + AssignBillingAddressToCart $assignBillingAddressToCart ) { + $this->quoteAddressFactory = $quoteAddressFactory; + $this->getCustomer = $getCustomer; $this->assignBillingAddressToCart = $assignBillingAddressToCart; - $this->createQuoteAddressByCustomerAddress = $createQuoteAddressByCustomerAddress; } /** @@ -49,9 +58,9 @@ public function __construct( * @param array $billingAddressInput * @return void * @throws GraphQlInputException - * @throws GraphQlNoSuchEntityException - * @throws GraphQlAuthorizationException * @throws GraphQlAuthenticationException + * @throws GraphQlAuthorizationException + * @throws GraphQlNoSuchEntityException */ public function execute(ContextInterface $context, CartInterface $cart, array $billingAddressInput): void { @@ -79,11 +88,15 @@ public function execute(ContextInterface $context, CartInterface $cart, array $b ); } - $billingAddress = $this->createQuoteAddressByCustomerAddress->execute( - $context, - $customerAddressId, - $addressInput - ); + if (null === $customerAddressId) { + $billingAddress = $this->quoteAddressFactory->createBasedOnInputData($addressInput); + } else { + $customer = $this->getCustomer->execute($context); + $billingAddress = $this->quoteAddressFactory->createBasedOnCustomerAddress( + (int)$customerAddressId, + (int)$customer->getId() + ); + } $this->assignBillingAddressToCart->execute($cart, $billingAddress, $useForShipping); } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCart.php index bbca7721754cb..6b0e2a311bf44 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCart.php @@ -7,7 +7,6 @@ namespace Magento\QuoteGraphQl\Model\Cart; -use Magento\CustomerGraphQl\Model\Customer\Address\GetCustomerAddress; use Magento\CustomerGraphQl\Model\Customer\GetCustomer; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; @@ -28,11 +27,6 @@ class SetShippingAddressesOnCart implements SetShippingAddressesOnCartInterface */ private $getCustomer; - /** - * @var GetCustomerAddress - */ - private $getCustomerAddress; - /** * @var AssignShippingAddressToCart */ @@ -41,18 +35,15 @@ class SetShippingAddressesOnCart implements SetShippingAddressesOnCartInterface /** * @param QuoteAddressFactory $quoteAddressFactory * @param GetCustomer $getCustomer - * @param GetCustomerAddress $getCustomerAddress * @param AssignShippingAddressToCart $assignShippingAddressToCart */ public function __construct( QuoteAddressFactory $quoteAddressFactory, GetCustomer $getCustomer, - GetCustomerAddress $getCustomerAddress, AssignShippingAddressToCart $assignShippingAddressToCart ) { $this->quoteAddressFactory = $quoteAddressFactory; $this->getCustomer = $getCustomer; - $this->getCustomerAddress = $getCustomerAddress; $this->assignShippingAddressToCart = $assignShippingAddressToCart; } @@ -86,8 +77,10 @@ public function execute(ContextInterface $context, CartInterface $cart, array $s $shippingAddress = $this->quoteAddressFactory->createBasedOnInputData($addressInput); } else { $customer = $this->getCustomer->execute($context); - $customerAddress = $this->getCustomerAddress->execute((int)$customerAddressId, (int)$customer->getId()); - $shippingAddress = $this->quoteAddressFactory->createBasedOnCustomerAddress($customerAddress); + $shippingAddress = $this->quoteAddressFactory->createBasedOnCustomerAddress( + (int)$customerAddressId, + (int)$customer->getId() + ); } $this->assignShippingAddressToCart->execute($cart, $shippingAddress); From 8a98f208245d381d3fff0bb22c47f757b89f6e07 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Thu, 28 Mar 2019 17:28:06 +0200 Subject: [PATCH 336/603] Fix wrong interface implementation. --- .../Controller/Adminhtml/Dashboard/ProductsViewed.php | 4 +++- .../Controller/Adminhtml/Dashboard/ProductsViewedTest.php | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Backend/Controller/Adminhtml/Dashboard/ProductsViewed.php b/app/code/Magento/Backend/Controller/Adminhtml/Dashboard/ProductsViewed.php index 216c730ccccc0..a42a44814cb0c 100644 --- a/app/code/Magento/Backend/Controller/Adminhtml/Dashboard/ProductsViewed.php +++ b/app/code/Magento/Backend/Controller/Adminhtml/Dashboard/ProductsViewed.php @@ -6,10 +6,12 @@ */ namespace Magento\Backend\Controller\Adminhtml\Dashboard; +use Magento\Framework\App\Action\HttpPostActionInterface; + /** * Get most viewed products controller. */ -class ProductsViewed extends AjaxBlock +class ProductsViewed extends AjaxBlock implements HttpPostActionInterface { /** * Gets most viewed products list diff --git a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/Dashboard/ProductsViewedTest.php b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/Dashboard/ProductsViewedTest.php index 595a33344c7e8..bd4dd0c8daf0c 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/Dashboard/ProductsViewedTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/Dashboard/ProductsViewedTest.php @@ -4,8 +4,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Backend\Controller\Adminhtml\Dashboard; +/** + * Test product viewed backend controller. + */ class ProductsViewedTest extends \Magento\TestFramework\TestCase\AbstractBackendController { /** @@ -14,6 +18,7 @@ class ProductsViewedTest extends \Magento\TestFramework\TestCase\AbstractBackend */ public function testExecute() { + $this->getRequest()->setMethod("POST"); $this->dispatch('backend/admin/dashboard/productsViewed/'); $this->assertEquals(200, $this->getResponse()->getHttpResponseCode()); From 5410e077c534127f3492d53f8ab3981691bed2e3 Mon Sep 17 00:00:00 2001 From: Jeff Coleman <jeff@jeffcolemanwrites.com> Date: Wed, 3 Apr 2019 00:42:30 -0700 Subject: [PATCH 337/603] fix to call Magento\Sales\Model\Order::getStoreId() only once --- .../Observer/SaveDownloadableOrderItemObserver.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php index fb4af4c3443a9..19339e4484ef6 100644 --- a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php +++ b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php @@ -92,14 +92,15 @@ public function execute(\Magento\Framework\Event\Observer $observer) if ($purchasedLink->getId()) { return $this; } + $storeId = $orderItem->getOrder()->getStoreId(); $orderStatusToEnableItem = $this->_scopeConfig->getValue( \Magento\Downloadable\Model\Link\Purchased\Item::XML_PATH_ORDER_ITEM_STATUS, ScopeInterface::SCOPE_STORE, - $orderItem->getOrder()->getStoreId() + $storeId ); if (!$product) { $product = $this->_createProductModel()->setStoreId( - $orderItem->getOrder()->getStoreId() + $storeId )->load( $orderItem->getProductId() ); From cae7e10ca75669cd7658113ec5ed6a9e4902f496 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Wed, 3 Apr 2019 11:21:16 +0300 Subject: [PATCH 338/603] Refactoring --- .../LoginAdminWithCredentialsActionGroup.xml | 22 ++++++++ .../Mftf/Test/CaptchaOnAdminLoginTest.xml | 50 +++++++++++-------- .../Test/TestCase/CaptchaOnAdminLoginTest.xml | 1 + 3 files changed, 51 insertions(+), 22 deletions(-) create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginAdminWithCredentialsActionGroup.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginAdminWithCredentialsActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginAdminWithCredentialsActionGroup.xml new file mode 100644 index 0000000000000..6aaa612b249b6 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginAdminWithCredentialsActionGroup.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="LoginAdminWithCredentialsActionGroup"> + <arguments> + <argument name="adminUser" type="string" /> + <argument name="adminPassword" type="string" /> + </arguments> + <amOnPage url="{{_ENV.MAGENTO_BACKEND_NAME}}" stepKey="navigateToAdmin"/> + <fillField selector="{{AdminLoginFormSection.username}}" userInput="{{adminUser}}" stepKey="fillUsername"/> + <fillField selector="{{AdminLoginFormSection.password}}" userInput="{{adminPassword}}" stepKey="fillPassword"/> + <click selector="{{AdminLoginFormSection.signIn}}" stepKey="clickLogin"/> + <closeAdminNotification stepKey="closeAdminNotification"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnAdminLoginTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnAdminLoginTest.xml index 80f1832200fc1..d830c0723ba89 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnAdminLoginTest.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnAdminLoginTest.xml @@ -29,34 +29,40 @@ <waitForPageLoad stepKey="waitForPageLoad1" /> <!-- Login as Admin with incorrect credentials 3 times --> - <fillField selector="{{AdminLoginFormSection.username}}" userInput="adminUser" stepKey="fillUsername1"/> - <fillField selector="{{AdminLoginFormSection.password}}" userInput="adminPassword" stepKey="fillPassword1"/> - <click selector="{{AdminLoginFormSection.signIn}}" stepKey="clickLogin1"/> - <see userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." selector="{{AdminLoginFormSection.error}}" stepKey="seeLoginError1"/> + <actionGroup ref="LoginAdminWithCredentialsActionGroup" stepKey="failedFirstLoginAdminUser"> + <argument name="adminUser" value="adminUser" /> + <argument name="adminPassword" value="INVALIDAdminPassword" /> + </actionGroup> + <see userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." + selector="{{AdminLoginFormSection.error}}" stepKey="seeFirstLoginError"/> - <fillField selector="{{AdminLoginFormSection.username}}" userInput="adminUser" stepKey="fillUsername2"/> - <fillField selector="{{AdminLoginFormSection.password}}" userInput="adminPassword" stepKey="fillPassword2"/> - <click selector="{{AdminLoginFormSection.signIn}}" stepKey="clickLogin2"/> - <see userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." selector="{{AdminLoginFormSection.error}}" stepKey="seeLoginError2"/> + <actionGroup ref="LoginAdminWithCredentialsActionGroup" stepKey="failedSecondLoginAdminUser"> + <argument name="adminUser" value="adminUser" /> + <argument name="adminPassword" value="INVALIDAdminPassword" /> + </actionGroup> + <see userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." + selector="{{AdminLoginFormSection.error}}" stepKey="seeSecondLoginError"/> - <fillField selector="{{AdminLoginFormSection.username}}" userInput="adminUser" stepKey="fillUsername3"/> - <fillField selector="{{AdminLoginFormSection.password}}" userInput="adminPassword" stepKey="fillPassword3"/> - <click selector="{{AdminLoginFormSection.signIn}}" stepKey="clickLogin3"/> - <see userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." selector="{{AdminLoginFormSection.error}}" stepKey="seeLoginError3"/> + <actionGroup ref="LoginAdminWithCredentialsActionGroup" stepKey="failedThirdLoginAdminUser"> + <argument name="adminUser" value="adminUser" /> + <argument name="adminPassword" value="INVALIDAdminPassword" /> + </actionGroup> + <see userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." + selector="{{AdminLoginFormSection.error}}" stepKey="seeThirdLoginError"/> <!-- Check captcha visibility on admin login page --> - <waitForElementVisible selector="{{AdminLoginFormSection.captchaField}}" stepKey="seeCaptchaField1"/> - <waitForElementVisible selector="{{AdminLoginFormSection.captchaImg}}" stepKey="seeCaptchaImage1"/> - <waitForElementVisible selector="{{AdminLoginFormSection.captchaReload}}" stepKey="seeCaptchaReloadButton1"/> + <waitForElementVisible selector="{{AdminLoginFormSection.captchaField}}" stepKey="seeFirstCaptchaField"/> + <waitForElementVisible selector="{{AdminLoginFormSection.captchaImg}}" stepKey="seeFirstCaptchaImage"/> + <waitForElementVisible selector="{{AdminLoginFormSection.captchaReload}}" stepKey="seeFirstCaptchaReloadButton"/> <!-- Submit form with incorrect captcha --> - <fillField selector="{{AdminLoginFormSection.username}}" userInput="adminUser" stepKey="fillUsername4"/> - <fillField selector="{{AdminLoginFormSection.password}}" userInput="adminPassword" stepKey="fillPassword4"/> - <fillField selector="{{AdminLoginFormSection.captchaField}}" userInput="incorrectCaptcha" stepKey="fillCaptcha4"/> - <click selector="{{AdminLoginFormSection.signIn}}" stepKey="clickLogin4"/> + <fillField selector="{{AdminLoginFormSection.username}}" userInput="adminUser" stepKey="fillAdminUserNameWithCaptcha"/> + <fillField selector="{{AdminLoginFormSection.password}}" userInput="adminPassword" stepKey="fillPasswordWithCaptcha"/> + <fillField selector="{{AdminLoginFormSection.captchaField}}" userInput="incorrectCaptcha" stepKey="fillCaptcha"/> + <click selector="{{AdminLoginFormSection.signIn}}" stepKey="clickLoginWithCaptcha"/> <see userInput="Incorrect CAPTCHA." selector="{{AdminLoginFormSection.error}}" stepKey="seeCaptchaError"/> - <waitForElementVisible selector="{{AdminLoginFormSection.captchaField}}" stepKey="seeCaptchaField2"/> - <waitForElementVisible selector="{{AdminLoginFormSection.captchaImg}}" stepKey="seeCaptchaImage2"/> - <waitForElementVisible selector="{{AdminLoginFormSection.captchaReload}}" stepKey="seeCaptchaReloadButton2"/> + <waitForElementVisible selector="{{AdminLoginFormSection.captchaField}}" stepKey="seeSecondCaptchaField"/> + <waitForElementVisible selector="{{AdminLoginFormSection.captchaImg}}" stepKey="seeSecondCaptchaImage"/> + <waitForElementVisible selector="{{AdminLoginFormSection.captchaReload}}" stepKey="seeSecondCaptchaReloadButton"/> </test> </tests> diff --git a/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnAdminLoginTest.xml b/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnAdminLoginTest.xml index 186439bb9f157..9242bfbef2374 100644 --- a/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnAdminLoginTest.xml +++ b/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnAdminLoginTest.xml @@ -12,6 +12,7 @@ <data name="customAdmin/data/captcha" xsi:type="string">111</data> <data name="pageTitle" xsi:type="string">Dashboard</data> <data name="configData" xsi:type="string">captcha_backend_login</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Backend\Test\Constraint\AssertBackendPageIsAvailable" /> </variation> </testCase> From c78535dfaa1dbd594d9f6a2bca37f3fb545a1919 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 2 Apr 2019 10:24:26 +0300 Subject: [PATCH 339/603] magento/magento2#21083: Static test fix. --- .../ConfigurableProduct/Model/LinkManagement.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php b/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php index 75cab12f63562..2f07f8b90ce7e 100644 --- a/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php +++ b/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php @@ -12,6 +12,8 @@ /** * Configurable product link management. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class LinkManagement implements \Magento\ConfigurableProduct\Api\LinkManagementInterface { @@ -110,6 +112,10 @@ public function getChildren($sku) /** * @inheritdoc + * @throws InputException + * @throws NoSuchEntityException + * @throws StateException + * @throws \Magento\Framework\Exception\CouldNotSaveException */ public function addChild($sku, $childSku) { @@ -153,6 +159,10 @@ public function addChild($sku, $childSku) /** * @inheritdoc + * @throws InputException + * @throws NoSuchEntityException + * @throws StateException + * @throws \Magento\Framework\Exception\CouldNotSaveException */ public function removeChild($sku, $childSku) { From 95760d50f8b7e914fd93d0487a179bb5c015eedc Mon Sep 17 00:00:00 2001 From: Davit_Zakharyan <davit_zakharyan@epam.com> Date: Wed, 3 Apr 2019 12:26:53 +0400 Subject: [PATCH 340/603] MAGETWO-91523: [2.3] Allowed countries restriction for a default website is applied to backend customer grid - Updated automated test script. --- ...iteCountryOptionsToDefaultActionGroup.xml} | 2 +- .../Mftf/Section/CountryOptionsSection.xml | 18 ++++++++ .../SetAccountSharingOptionActionGroup.xml | 25 ----------- ...dminStoresCustomerConfigurationSection.xml | 3 -- .../Test/Mftf/Section/GeneralSection.xml | 5 --- .../Test/Mftf/Data/CustomerConfigData.xml | 7 ++++ .../customer_config_account_sharing-meta.xml | 12 ++++++ .../Section/AdminCustomerConfigSection.xml | 3 ++ .../Section/AdminCustomerFiltersSection.xml | 1 + ...CountriesRestrictionApplyOnBackendTest.xml | 41 +++++++++++-------- .../Section/AdminDataGridHeaderSection.xml | 1 - 11 files changed, 65 insertions(+), 53 deletions(-) rename app/code/Magento/{Config/Test/Mftf/ActionGroup/SetMainWebsiteCountryOptionsToDefaultActionGroup.xml => Backend/Test/Mftf/ActionGroup/SetWebsiteCountryOptionsToDefaultActionGroup.xml} (93%) create mode 100644 app/code/Magento/Backend/Test/Mftf/Section/CountryOptionsSection.xml delete mode 100644 app/code/Magento/Config/Test/Mftf/ActionGroup/SetAccountSharingOptionActionGroup.xml diff --git a/app/code/Magento/Config/Test/Mftf/ActionGroup/SetMainWebsiteCountryOptionsToDefaultActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetWebsiteCountryOptionsToDefaultActionGroup.xml similarity index 93% rename from app/code/Magento/Config/Test/Mftf/ActionGroup/SetMainWebsiteCountryOptionsToDefaultActionGroup.xml rename to app/code/Magento/Backend/Test/Mftf/ActionGroup/SetWebsiteCountryOptionsToDefaultActionGroup.xml index 9b922df0b3e3e..4519648eb1d1b 100644 --- a/app/code/Magento/Config/Test/Mftf/ActionGroup/SetMainWebsiteCountryOptionsToDefaultActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetWebsiteCountryOptionsToDefaultActionGroup.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="SetMainWebsiteCountryOptionsToDefaultActionGroup"> + <actionGroup name="SetWebsiteCountryOptionsToDefaultActionGroup"> <conditionalClick selector="{{CountryOptionsSection.countryOptions}}" dependentSelector="{{CountryOptionsSection.countryOptionsOpen}}" visible="false" stepKey="clickOnStoreInformation3"/> <waitForElementVisible selector="{{CountryOptionsSection.topDestinations}}" stepKey="waitCheckboxToBeVisible3"/> <checkOption selector="{{CountryOptionsSection.generalCountryAllowInherit}}" stepKey="setToDefault1"/> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/CountryOptionsSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/CountryOptionsSection.xml new file mode 100644 index 0000000000000..2e2e5aec35ecd --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Section/CountryOptionsSection.xml @@ -0,0 +1,18 @@ +<?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="CountryOptionsSection"> + <element name="allowedCountries" type="select" selector="#general_country_allow"/> + <element name="notAllowedCountry" type="button" selector="#general_country_allow option:not([selected])"/> + <element name="generalCountryAllowInherit" type="checkbox" selector="#general_country_allow_inherit"/> + <element name="generalCountryDefaultInherit" type="checkbox" selector="#general_country_default_inherit"/> + <element name="generalCountryDefault" type="select" selector="#general_country_default"/> + </section> +</sections> diff --git a/app/code/Magento/Config/Test/Mftf/ActionGroup/SetAccountSharingOptionActionGroup.xml b/app/code/Magento/Config/Test/Mftf/ActionGroup/SetAccountSharingOptionActionGroup.xml deleted file mode 100644 index 113383a296d08..0000000000000 --- a/app/code/Magento/Config/Test/Mftf/ActionGroup/SetAccountSharingOptionActionGroup.xml +++ /dev/null @@ -1,25 +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="SetAccountSharingOptionActionGroup"> - <arguments> - <argument name="option" defaultValue="Per Website" type="string"/> - </arguments> - <amOnPage url="{{AdminStoresCustomerConfigurationPage.url}}" stepKey="goToCustomerConfigurationPage"/> - <conditionalClick selector="{{AdminStoresCustomerConfigurationSection.accountSharingOptionsTab}}" dependentSelector="{{AdminStoresCustomerConfigurationSection.shareCustomerAccountInherit}}" visible="false" stepKey="expandAccountSharingOptionsTab"/> - <waitForElementVisible selector="{{AdminStoresCustomerConfigurationSection.shareCustomerAccountInherit}}" stepKey="waitSystemValueCheckboxToBeVisible"/> - <uncheckOption selector="{{AdminStoresCustomerConfigurationSection.shareCustomerAccountInherit}}" stepKey="uncheck"/> - <selectOption selector="{{AdminStoresCustomerConfigurationSection.shareCustomerAccount}}" userInput="{{option}}" stepKey="setAccountSharingOption"/> - <click selector="{{AdminStoresCustomerConfigurationSection.accountSharingOptionsTab}}" stepKey="collapseTab"/> - <click selector="{{ContentManagementSection.Save}}" stepKey="clickSaveConfig"/> - <waitForPageLoad stepKey="waitConfigToBeSaved"/> - <seeElement selector="{{AdminMessagesSection.success}}" stepKey="seeSuccessMessage"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Config/Test/Mftf/Section/AdminStoresCustomerConfigurationSection.xml b/app/code/Magento/Config/Test/Mftf/Section/AdminStoresCustomerConfigurationSection.xml index 634d3490df05c..823be383ce123 100644 --- a/app/code/Magento/Config/Test/Mftf/Section/AdminStoresCustomerConfigurationSection.xml +++ b/app/code/Magento/Config/Test/Mftf/Section/AdminStoresCustomerConfigurationSection.xml @@ -10,8 +10,5 @@ <element name="createNewAccOpt" type="button" selector="#customer_create_account-head"/> <element name="enableAutoAssignCustomerGroup" type="button" selector="#customer_create_account_auto_group_assign"/> <element name="groupForValidVATIdIntraUnion" type="select" selector="#customer_create_account_viv_intra_union_group"/> - <element name="accountSharingOptionsTab" type="button" selector="#customer_account_share-head"/> - <element name="shareCustomerAccountInherit" type="checkbox" selector="#customer_account_share_scope_inherit"/> - <element name="shareCustomerAccount" type="select" selector="#customer_account_share_scope"/> </section> </sections> diff --git a/app/code/Magento/Config/Test/Mftf/Section/GeneralSection.xml b/app/code/Magento/Config/Test/Mftf/Section/GeneralSection.xml index dbec3683cf2d1..d007c860782aa 100644 --- a/app/code/Magento/Config/Test/Mftf/Section/GeneralSection.xml +++ b/app/code/Magento/Config/Test/Mftf/Section/GeneralSection.xml @@ -38,11 +38,6 @@ <element name="countryOptions" type="button" selector="#general_country-head"/> <element name="countryOptionsOpen" type="button" selector="#general_country-head.open"/> <element name="topDestinations" type="select" selector="#general_country_destinations"/> - <element name="allowedCountries" type="select" selector="#general_country_allow"/> - <element name="notAllowedCountry" type="button" selector="#general_country_allow option:not([selected])"/> - <element name="generalCountryAllowInherit" type="checkbox" selector="#general_country_allow_inherit"/> - <element name="generalCountryDefaultInherit" type="checkbox" selector="#general_country_default_inherit"/> - <element name="generalCountryDefault" type="select" selector="#general_country_default"/> </section> <section name="StateOptionsSection"> <element name="stateOptions" type="button" selector="#general_region-head"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerConfigData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerConfigData.xml index 3cbd70d342824..11a47459ab7b3 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerConfigData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerConfigData.xml @@ -21,4 +21,11 @@ <entity name="GlobalCustomerAccountSharing" type="account_share_scope_value"> <data key="value">0</data> </entity> + + <entity name="CustomerAccountSharingSystemValue" type="customer_account_sharing_config_inherit"> + <requiredEntity type="account_share_scope_inherit">CustomerAccountSharingInherit</requiredEntity> + </entity> + <entity name="CustomerAccountSharingInherit" type="account_share_scope_inherit"> + <data key="inherit">true</data> + </entity> </entities> diff --git a/app/code/Magento/Customer/Test/Mftf/Metadata/customer_config_account_sharing-meta.xml b/app/code/Magento/Customer/Test/Mftf/Metadata/customer_config_account_sharing-meta.xml index 41701bfac11ad..c3132b5b6a44f 100644 --- a/app/code/Magento/Customer/Test/Mftf/Metadata/customer_config_account_sharing-meta.xml +++ b/app/code/Magento/Customer/Test/Mftf/Metadata/customer_config_account_sharing-meta.xml @@ -18,4 +18,16 @@ </object> </object> </operation> + <operation name="CustomerAccountShareConfigInherit" dataType="customer_account_sharing_config_inherit" type="create" auth="adminFormKey" url="/admin/system_config/save/section/customer/" + method="POST"> + <object key="groups" dataType="customer_account_sharing_config_inherit"> + <object key="account_share" dataType="customer_account_sharing_config_inherit"> + <object key="fields" dataType="customer_account_sharing_config_inherit"> + <object key="scope" dataType="account_share_scope_inherit"> + <field key="inherit">boolean</field> + </object> + </object> + </object> + </object> + </operation> </operations> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerConfigSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerConfigSection.xml index 9e104eb52cf90..a934d71397b8c 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerConfigSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerConfigSection.xml @@ -8,5 +8,8 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminCustomerConfigSection"> <element name="customerDataLifetime" type="input" selector="#customer_online_customers_section_data_lifetime"/> + <element name="accountSharingOptionsTab" type="button" selector="#customer_account_share-head"/> + <element name="shareCustomerAccountInherit" type="checkbox" selector="#customer_account_share_scope_inherit"/> + <element name="shareCustomerAccount" type="select" selector="#customer_account_share_scope"/> </section> </sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerFiltersSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerFiltersSection.xml index 25617ca05dd44..17a4a283c2648 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerFiltersSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerFiltersSection.xml @@ -18,5 +18,6 @@ <element name="clearAll" type="button" selector=".admin__data-grid-header .action-tertiary.action-clear" timeout="30"/> <element name="viewDropdown" type="button" selector=".admin__data-grid-action-bookmarks button.admin__action-dropdown"/> <element name="viewBookmark" type="button" selector="//div[contains(@class, 'admin__data-grid-action-bookmarks')]/ul/li/div/a[text() = '{{label}}']" parameterized="true" timeout="30"/> + <element name="countryOptions" type="button" selector=".admin__data-grid-filters select[name=billing_country_id] option"/> </section> </sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml index d48320123f82d..ed353403fc15d 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml @@ -11,7 +11,7 @@ <annotations> <title value="Country filter on Customers page when allowed countries restriction for a default website is applied"/> <description value="Country filter on Customers page when allowed countries restriction for a default website is applied"/> - <features value="Module/ Customer"/> + <features value="Customer"/> <severity value="MAJOR"/> <testCaseId value="MC-6441"/> <useCaseId value="MAGETWO-91523"/> @@ -23,27 +23,29 @@ <requiredEntity createDataKey="createCategory"/> </createData> <actionGroup ref="LoginActionGroup" stepKey="login"/> - <!--Create new website,store and store view--> + <comment userInput="Create new website,store and store view" stepKey="createWebsite"/> <amOnPage url="{{AdminSystemStorePage.url}}" stepKey="goToAdminSystemStorePage"/> - <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="AdminCreateNewWebsite"> + <actionGroup ref="AdminCreateWebsite" stepKey="AdminCreateNewWebsite"> <argument name="newWebsiteName" value="{{NewWebSiteData.name}}"/> <argument name="websiteCode" value="{{NewWebSiteData.code}}"/> </actionGroup> - <actionGroup ref="AdminCreateNewStoreGroupActionGroup" stepKey="AdminCreateNewStore"> + <actionGroup ref="AdminCreateNewStore" stepKey="AdminCreateNewStore"> <argument name="website" value="{{NewWebSiteData.name}}"/> <argument name="storeGroupName" value="{{NewStoreData.name}}"/> <argument name="storeGroupCode" value="{{NewStoreData.code}}"/> </actionGroup> - <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="AdminCreateNewStoreView"> + <actionGroup ref="AdminCreateStoreView" stepKey="AdminCreateNewStoreView"> <argument name="StoreGroup" value="NewStoreData"/> </actionGroup> <!--Set account sharing option - Default value is 'Per Website'--> - <actionGroup ref="SetAccountSharingOptionActionGroup" stepKey="setAccountSharingOptionToDefault"/> + <comment userInput="Set account sharing option - Default value is 'Per Website'" stepKey="setAccountSharingOption"/> + <createData entity="CustomerAccountSharingDefault" stepKey="setToAccountSharingToDefault"/> <magentoCLI command="indexer:reindex" stepKey="reindex"/> </before> <after> <!--delete all created data and set main website country options to default--> + <comment userInput="Delete all created data and set main website country options to default" stepKey="resetConfigToDefault"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> @@ -54,22 +56,22 @@ <actionGroup ref="AdminSwitchWebsiteActionGroup" stepKey="adminSwitchWebsiteActionGroup"> <argument name="website" value="_defaultWebsite"/> </actionGroup> - <actionGroup ref="SetMainWebsiteCountryOptionsToDefaultActionGroup" stepKey="setCountryOptionsToDefault"/> + <actionGroup ref="SetWebsiteCountryOptionsToDefaultActionGroup" stepKey="setCountryOptionsToDefault"/> + <createData entity="CustomerAccountSharingSystemValue" stepKey="setAccountSharingToSystemValue"/> <actionGroup ref="logout" stepKey="logout"/> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> </after> <!--Check that all countries are allowed initially and get amount--> + <comment userInput="Check that all countries are allowed initially and get amount" stepKey="checkAllCountriesAreAllowed"/> <actionGroup ref="NavigateToConfigurationGeneralPage" stepKey="navigateToConfigGeneralPage"/> - <conditionalClick selector="{{CountryOptionsSection.countryOptions}}" dependentSelector="{{CountryOptionsSection.countryOptionsOpen}}" visible="false" stepKey="clickOnStoreInformation"/> - <waitForElementVisible selector="{{CountryOptionsSection.allowedCountries}}" stepKey="waitTabToExpand"/> - <executeJS function="return document.querySelectorAll('{{CountryOptionsSection.allowedCountries}} option').length" stepKey="CountriesAmount"/> - <checkOption selector="{{CountryOptionsSection.generalCountryAllowInherit}}" stepKey="markAllCountriesAsAvailable"/> - <click selector="{{CountryOptionsSection.countryOptions}}" stepKey="collapseTab"/> - <click selector="{{ContentManagementSection.Save}}" stepKey="saveConfig"/> - <waitForPageLoad stepKey="waitForSavingSystemConfiguration"/> - <see userInput="You saved the configuration." stepKey="seeSuccessMessage"/> + <createData entity="DisableAdminAccountAllowCountry" stepKey="setDefaultValueForAllowCountries"/> + <executeJS function="return document.querySelectorAll('{{CountryOptionsSection.allowedCountries}} option').length" stepKey="countriesAmount"/> <!-- Create customer for US --> + <comment userInput="Create customer for US" stepKey="createUSCustomer"/> <createData entity="Simple_US_CA_Customer" stepKey="createCustomer"/> - <!-- Switch to first website, allow only Canada and set Canada as default country--> + <!-- Switch to first website, allow only Canada and set Canada as default country --> + <comment userInput="Switch to first website, allow only Canada and set Canada as default country" stepKey="setCanadaAsDefaultCountry"/> <actionGroup ref="AdminSwitchWebsiteActionGroup" stepKey="adminSwitchWebsiteActionGroup"> <argument name="website" value="_defaultWebsite"/> </actionGroup> @@ -82,6 +84,7 @@ <click selector="{{ContentManagementSection.Save}}" stepKey="saveConfig2"/> <waitForPageLoad stepKey="waitForSavingSystemConfiguration2"/> <!--Switch to second website and allow all countries except Canada--> + <comment userInput="Switch to second website and allow all countries except Canada" stepKey="switchToWebsiteAndAllowOnlyCanada"/> <actionGroup ref="AdminSwitchWebsiteActionGroup" stepKey="adminSwitchWebsiteActionGroup2"> <argument name="website" value="NewWebSiteData"/> </actionGroup> @@ -94,6 +97,7 @@ <amOnPage url="{{AdminEditCustomerPage.url($$createCustomer.id$$)}}" stepKey="goToCustomerEditPage"/> <waitForPageLoad stepKey="waitPageToLoad"/> <!--Open created customer details page and change US address to Canada address--> + <comment userInput="Open created customer details page and change US address to Canada address" stepKey="changeCustomerAddressToCanada"/> <actionGroup ref="OpenEditCustomerAddressFromAdminActionGroup" stepKey="editCustomerAddress"> <argument name="address" value="US_Address_CA"/> </actionGroup> @@ -104,10 +108,11 @@ <click stepKey="saveCustomer" selector="{{AdminCustomerAccountInformationSection.saveCustomerAndContinueEdit}}"/> <waitForPageLoad stepKey="waitForCustomersPage"/> <!--Go to Customers grid and check that filter countries amount is the same as initial allowed countries amount--> + <comment userInput="Go to Customers grid and check that filter countries amount is the same as initial allowed countries amount" stepKey="compareCountriesAmount"/> <amOnPage url="{{AdminCustomerPage.url}}" stepKey="goToCustomersGrid"/> <waitForPageLoad stepKey="waitForCustomersGrid"/> <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openFiltersSectionOnCustomersGrid"/> - <executeJS function="var len = document.querySelectorAll('{{AdminDataGridHeaderSection.countryOptions}}').length; return len-1;" stepKey="CountriesAmount2"/> - <assertEquals expected='($CountriesAmount)' expectedType="integer" actual="($CountriesAmount2)" stepKey="assertCountryAmounts"/> + <executeJS function="var len = document.querySelectorAll('{{AdminCustomerFiltersSection.countryOptions}}').length; return len-1;" stepKey="countriesAmount2"/> + <assertEquals expected='($countriesAmount)' expectedType="integer" actual="($countriesAmount2)" stepKey="assertCountryAmounts"/> </test> </tests> diff --git a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridHeaderSection.xml b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridHeaderSection.xml index f881cf5c05cfc..4ee38e30f98e6 100644 --- a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridHeaderSection.xml +++ b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridHeaderSection.xml @@ -16,7 +16,6 @@ <element name="filters" type="button" selector="button[data-action='grid-filter-expand']" timeout="30"/> <element name="filterFieldInput" type="input" selector=".admin__data-grid-filters input[name='{{name}}']" parameterized="true"/> <element name="filterFieldSelect" type="select" selector=".admin__data-grid-filters select[name='{{name}}']" parameterized="true"/> - <element name="countryOptions" type="button" selector=".admin__data-grid-filters select[name=billing_country_id] option"/> <element name="cancelFilters" type="button" selector="button[data-action='grid-filter-cancel']" timeout="30"/> <element name="applyFilters" type="button" selector="button[data-action='grid-filter-apply']" timeout="30"/> <element name="clearFilters" type="button" selector=".admin__data-grid-header [data-action='grid-filter-reset']" timeout="30"/> From 342dc530ba86c6df56b5346139f305cf7cc24736 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Wed, 3 Apr 2019 12:49:16 +0300 Subject: [PATCH 341/603] MAGETWO-98620: Shipping quote in cart not persisted for Guest customers when Persistent Shopping Cart is enabled --- .../Magento/Persistent/Model/QuoteManager.php | 1 + .../CheckExpirePersistentQuoteObserver.php | 10 ++- .../SetQuotePersistentDataObserver.php | 8 +- .../ShippingQuotePersistedForGuestTest.xml | 84 +++++++++++++++++++ ...CheckExpirePersistentQuoteObserverTest.php | 20 ++++- .../SetQuotePersistentDataObserverTest.php | 4 +- 6 files changed, 118 insertions(+), 9 deletions(-) create mode 100644 app/code/Magento/Persistent/Test/Mftf/Test/ShippingQuotePersistedForGuestTest.xml diff --git a/app/code/Magento/Persistent/Model/QuoteManager.php b/app/code/Magento/Persistent/Model/QuoteManager.php index 35c2c70be30dc..34f84aa2c3cfc 100644 --- a/app/code/Magento/Persistent/Model/QuoteManager.php +++ b/app/code/Magento/Persistent/Model/QuoteManager.php @@ -87,6 +87,7 @@ public function setGuest($checkQuote = false) ->setCustomerLastname(null) ->setCustomerGroupId(\Magento\Customer\Api\Data\GroupInterface::NOT_LOGGED_IN_ID) ->setIsPersistent(false) + ->setCustomerIsGuest(true) ->removeAllAddresses(); //Create guest addresses $quote->getShippingAddress(); diff --git a/app/code/Magento/Persistent/Observer/CheckExpirePersistentQuoteObserver.php b/app/code/Magento/Persistent/Observer/CheckExpirePersistentQuoteObserver.php index f3720960ca6e5..524cf7638af84 100644 --- a/app/code/Magento/Persistent/Observer/CheckExpirePersistentQuoteObserver.php +++ b/app/code/Magento/Persistent/Observer/CheckExpirePersistentQuoteObserver.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -8,6 +7,9 @@ use Magento\Framework\Event\ObserverInterface; +/** + * Observer of expired session + */ class CheckExpirePersistentQuoteObserver implements ObserverInterface { /** @@ -107,8 +109,12 @@ public function execute(\Magento\Framework\Event\Observer $observer) !$this->_persistentSession->isPersistent() && !$this->_customerSession->isLoggedIn() && $this->_checkoutSession->getQuoteId() && - !$this->isRequestFromCheckoutPage($this->request) + !$this->isRequestFromCheckoutPage($this->request) && // persistent session does not expire on onepage checkout page + ( + $this->_checkoutSession->getQuote()->getIsPersistent() || + $this->_checkoutSession->getQuote()->getCustomerIsGuest() + ) ) { $this->_eventManager->dispatch('persistent_session_expired'); $this->quoteManager->expire(); diff --git a/app/code/Magento/Persistent/Observer/SetQuotePersistentDataObserver.php b/app/code/Magento/Persistent/Observer/SetQuotePersistentDataObserver.php index db6b6d1ee370d..d7183bb5a6602 100644 --- a/app/code/Magento/Persistent/Observer/SetQuotePersistentDataObserver.php +++ b/app/code/Magento/Persistent/Observer/SetQuotePersistentDataObserver.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -8,6 +7,9 @@ use Magento\Framework\Event\ObserverInterface; +/** + * Observer for setting "is_persistent" value to quote + */ class SetQuotePersistentDataObserver implements ObserverInterface { /** @@ -73,8 +75,8 @@ public function execute(\Magento\Framework\Event\Observer $observer) } if (( - ($this->_persistentSession->isPersistent() && !$this->_customerSession->isLoggedIn()) - && !$this->_persistentData->isShoppingCartPersist() + ($this->_persistentSession->isPersistent()) + && $this->_persistentData->isShoppingCartPersist() ) && $this->quoteManager->isPersistent() ) { diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/ShippingQuotePersistedForGuestTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/ShippingQuotePersistedForGuestTest.xml new file mode 100644 index 0000000000000..e5c77ee414362 --- /dev/null +++ b/app/code/Magento/Persistent/Test/Mftf/Test/ShippingQuotePersistedForGuestTest.xml @@ -0,0 +1,84 @@ +<?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="ShippingQuotePersistedForGuestTest"> + <annotations> + <features value="Persistent"/> + <stories value="Guest checkout"/> + <title value="Estimate Shipping and Tax block sections on shipping cart saving correctly for Guest."/> + <description value="Verify that 'Estimate Shipping and Tax' block sections on shipping cart saving correctly for Guest after switching to another page. And check that the shopping cart is cleared after reset persistent cookie."/> + <severity value="CRITICAL"/> + <testCaseId value="MAGETWO-99025"/> + <useCaseId value="MAGETWO-98620"/> + <group value="persistent"/> + </annotations> + <before> + <!--Enabled The Persistent Shopping Cart feature --> + <createData entity="PersistentConfigEnabled" stepKey="enablePersistent"/> + <createData entity="PersistentLogoutClearDisable" stepKey="persistentLogoutClearDisable"/> + <!--Create simple product--> + <createData entity="SimpleProduct2" stepKey="createProduct"> + <field key="price">150</field> + </createData> + <!--Create customer--> + <createData entity="Simple_US_Customer" stepKey="createCustomer"> + <field key="firstname">John1</field> + <field key="lastname">Doe1</field> + </createData> + </before> + <after> + <!--Revert persistent configuration to default--> + <createData entity="PersistentConfigDefault" stepKey="setDefaultPersistentState"/> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <!--Step 1: Login as a Customer with remember me checked--> + <actionGroup ref="CustomerLoginOnStorefrontWithRememberMeChecked" stepKey="loginToStorefrontAccountWithRememberMeChecked"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + <!--Step 2: Open the Product Page and add the product to shopping cart--> + <amOnPage url="{{StorefrontProductPage.url($$createProduct.custom_attributes[url_key]$$)}}" stepKey="navigateToProductPageAsLoggedUser"/> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProductToCartAsLoggedUser"> + <argument name="productName" value="$$createProduct.name$$"/> + </actionGroup> + <!--Step 3: Log out, reset persistent cookie and go to homepage--> + <amOnPage url="{{StorefrontCustomerSignOutPage.url}}" stepKey="signOut"/> + <waitForLoadingMaskToDisappear stepKey="waitSignOutPage"/> + <resetCookie userInput="persistent_shopping_cart" stepKey="resetPersistentCookie"/> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnHomePageAfterResetPersistentCookie"/> + <waitForPageLoad stepKey="waitHomePageLoadAfterResetCookie"/> + <!--Check that the minicart is empty--> + <actionGroup ref="assertMiniCartEmpty" after="waitHomePageLoadAfterResetCookie" stepKey="seeMinicartEmpty"/> + <!--Step 4: Add the product to shopping cart and open cart--> + <amOnPage url="{{StorefrontProductPage.url($$createProduct.custom_attributes[url_key]$$)}}" stepKey="navigateToProductPageAsGuestUser"/> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProductToCartAsGuestUser"> + <argument name="productName" value="$$createProduct.name$$"/> + </actionGroup> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="goToShoppingCartBeforeChangeShippingAndTaxSection"/> + <!--Step 5: Open Estimate Shipping and Tax block and fill the sections--> + <conditionalClick selector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" dependentSelector="{{CheckoutCartSummarySection.country}}" visible="false" stepKey="expandEstimateShippingAndTax" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask"/> + <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="{{US_Address_CA.country}}" stepKey="selectUSCountry"/> + <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="{{US_Address_CA.state}}" stepKey="selectCaliforniaRegion"/> + <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="{{US_Address_CA.postcode}}" stepKey="inputPostCode"/> + <!--Step 6: Go to Homepage--> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToHomePageAfterChangingShippingAndTaxSection"/> + <!--Step 7: Go to shopping cart and check "Estimate Shipping and Tax" fields values are saved--> + <actionGroup ref="clickViewAndEditCartFromMiniCart" after="goToHomePageAfterChangingShippingAndTaxSection" stepKey="goToShoppingCartAfterChangingShippingAndTaxSection"/> + <conditionalClick selector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" dependentSelector="{{CheckoutCartSummarySection.country}}" visible="false" stepKey="expandEstimateShippingAndTaxAfterChanging" /> + <seeOptionIsSelected selector="{{CheckoutCartSummarySection.country}}" userInput="{{US_Address_CA.country}}" stepKey="checkCustomerCountry" /> + <seeOptionIsSelected selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="{{US_Address_CA.state}}" stepKey="checkCustomerRegion" /> + <grabValueFrom selector="{{CheckoutCartSummarySection.postcode}}" stepKey="grabTextPostCode"/> + <assertEquals message="Customer postcode is invalid" stepKey="checkCustomerPostcode"> + <expectedResult type="string">{{US_Address_CA.postcode}}</expectedResult> + <actualResult type="variable">grabTextPostCode</actualResult> + </assertEquals> + </test> +</tests> diff --git a/app/code/Magento/Persistent/Test/Unit/Observer/CheckExpirePersistentQuoteObserverTest.php b/app/code/Magento/Persistent/Test/Unit/Observer/CheckExpirePersistentQuoteObserverTest.php index 46dda1be365d4..b096dd2317a33 100644 --- a/app/code/Magento/Persistent/Test/Unit/Observer/CheckExpirePersistentQuoteObserverTest.php +++ b/app/code/Magento/Persistent/Test/Unit/Observer/CheckExpirePersistentQuoteObserverTest.php @@ -1,12 +1,16 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Persistent\Test\Unit\Observer; +use Magento\Quote\Model\Quote; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class CheckExpirePersistentQuoteObserverTest extends \PHPUnit\Framework\TestCase { /** @@ -54,6 +58,11 @@ class CheckExpirePersistentQuoteObserverTest extends \PHPUnit\Framework\TestCase */ private $requestMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject|Quote + */ + private $quoteMock; + /** * @inheritdoc */ @@ -83,6 +92,10 @@ protected function setUp() $this->checkoutSessionMock, $this->requestMock ); + $this->quoteMock = $this->getMockBuilder(Quote::class) + ->setMethods(['getCustomerIsGuest', 'getIsPersistent']) + ->disableOriginalConstructor() + ->getMock(); } public function testExecuteWhenCanNotApplyPersistentData() @@ -133,6 +146,11 @@ public function testExecuteWhenPersistentIsEnabled( ->willReturn(true); $this->persistentHelperMock->expects($this->once())->method('isEnabled')->willReturn(true); $this->sessionMock->expects($this->once())->method('isPersistent')->willReturn(false); + $this->checkoutSessionMock + ->method('getQuote') + ->willReturn($this->quoteMock); + $this->quoteMock->method('getCustomerIsGuest')->willReturn(true); + $this->quoteMock->method('getIsPersistent')->willReturn(true); $this->customerSessionMock ->expects($this->atLeastOnce()) ->method('isLoggedIn') diff --git a/app/code/Magento/Persistent/Test/Unit/Observer/SetQuotePersistentDataObserverTest.php b/app/code/Magento/Persistent/Test/Unit/Observer/SetQuotePersistentDataObserverTest.php index 6724743789cea..d74aaa1c90362 100644 --- a/app/code/Magento/Persistent/Test/Unit/Observer/SetQuotePersistentDataObserverTest.php +++ b/app/code/Magento/Persistent/Test/Unit/Observer/SetQuotePersistentDataObserverTest.php @@ -83,7 +83,6 @@ public function testExecuteWhenQuoteNotExist() ->method('getEvent') ->will($this->returnValue($this->eventManagerMock)); $this->eventManagerMock->expects($this->once())->method('getQuote'); - $this->customerSessionMock->expects($this->never())->method('isLoggedIn'); $this->model->execute($this->observerMock); } @@ -98,8 +97,7 @@ public function testExecuteWhenSessionIsPersistent() ->expects($this->once()) ->method('getQuote') ->will($this->returnValue($this->quoteMock)); - $this->customerSessionMock->expects($this->once())->method('isLoggedIn')->will($this->returnValue(false)); - $this->helperMock->expects($this->once())->method('isShoppingCartPersist')->will($this->returnValue(false)); + $this->helperMock->expects($this->once())->method('isShoppingCartPersist')->will($this->returnValue(true)); $this->quoteManagerMock->expects($this->once())->method('isPersistent')->will($this->returnValue(true)); $this->quoteMock->expects($this->once())->method('setIsPersistent')->with(true); $this->model->execute($this->observerMock); From a56b9877a86235990c9dcb888c86a32cb251b8b3 Mon Sep 17 00:00:00 2001 From: Jayanka <jayan@codilar.com> Date: Wed, 3 Apr 2019 15:47:55 +0530 Subject: [PATCH 342/603] save_parameters_in_session set to true for admin user grid --- .../User/view/adminhtml/layout/adminhtml_user_grid_block.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/User/view/adminhtml/layout/adminhtml_user_grid_block.xml b/app/code/Magento/User/view/adminhtml/layout/adminhtml_user_grid_block.xml index a4bc9aa5ed48b..8289b3e730d5d 100644 --- a/app/code/Magento/User/view/adminhtml/layout/adminhtml_user_grid_block.xml +++ b/app/code/Magento/User/view/adminhtml/layout/adminhtml_user_grid_block.xml @@ -16,6 +16,7 @@ <argument name="default_sort" xsi:type="string">username</argument> <argument name="default_dir" xsi:type="string">asc</argument> <argument name="grid_url" xsi:type="url" path="*/*/roleGrid"/> + <argument name="save_parameters_in_session" xsi:type="boolean">true</argument> </arguments> <block class="Magento\Backend\Block\Widget\Grid\ColumnSet" as="grid.columnSet" name="permission.user.grid.columnSet"> <arguments> From 6422fb26203140bd15fb86fc2d21ca6b8fc8c055 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Wed, 3 Apr 2019 14:40:50 +0300 Subject: [PATCH 343/603] MAGETWO-98620: Shipping quote in cart not persisted for Guest customers when Persistent Shopping Cart is enabled --- app/code/Magento/Persistent/Model/QuoteManager.php | 2 ++ .../Persistent/Observer/CheckExpirePersistentQuoteObserver.php | 2 ++ .../Persistent/Observer/SetQuotePersistentDataObserver.php | 2 ++ 3 files changed, 6 insertions(+) diff --git a/app/code/Magento/Persistent/Model/QuoteManager.php b/app/code/Magento/Persistent/Model/QuoteManager.php index 34f84aa2c3cfc..8ae22e4c26c6f 100644 --- a/app/code/Magento/Persistent/Model/QuoteManager.php +++ b/app/code/Magento/Persistent/Model/QuoteManager.php @@ -7,6 +7,8 @@ /** * Class QuoteManager + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class QuoteManager { diff --git a/app/code/Magento/Persistent/Observer/CheckExpirePersistentQuoteObserver.php b/app/code/Magento/Persistent/Observer/CheckExpirePersistentQuoteObserver.php index 524cf7638af84..79fdf44c3c551 100644 --- a/app/code/Magento/Persistent/Observer/CheckExpirePersistentQuoteObserver.php +++ b/app/code/Magento/Persistent/Observer/CheckExpirePersistentQuoteObserver.php @@ -9,6 +9,8 @@ /** * Observer of expired session + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class CheckExpirePersistentQuoteObserver implements ObserverInterface { diff --git a/app/code/Magento/Persistent/Observer/SetQuotePersistentDataObserver.php b/app/code/Magento/Persistent/Observer/SetQuotePersistentDataObserver.php index d7183bb5a6602..2803bc998dcbe 100644 --- a/app/code/Magento/Persistent/Observer/SetQuotePersistentDataObserver.php +++ b/app/code/Magento/Persistent/Observer/SetQuotePersistentDataObserver.php @@ -9,6 +9,8 @@ /** * Observer for setting "is_persistent" value to quote + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class SetQuotePersistentDataObserver implements ObserverInterface { From c79c277b3ccccae78be46f5e08aa2a57fea02119 Mon Sep 17 00:00:00 2001 From: Niklas <niklas@lynks.se> Date: Wed, 3 Apr 2019 14:12:44 +0200 Subject: [PATCH 344/603] setAttributeSetFilter accepts both integer and integer-array --- .../Eav/Model/ResourceModel/Entity/Attribute/Collection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php index cec415e513677..d70e2e0e06e96 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php @@ -128,7 +128,7 @@ public function setEntityTypeFilter($type) /** * Specify attribute set filter * - * @param int $setId + * @param int|int[] $setId * @return $this */ public function setAttributeSetFilter($setId) From bc3ef7ad15b23869face298c51b2b3bd301326f8 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Tue, 2 Apr 2019 12:43:09 +0300 Subject: [PATCH 345/603] Fix static tests. --- lib/internal/Magento/Framework/App/Http.php | 11 ++++-- .../Framework/App/Test/Unit/HttpTest.php | 2 +- .../Test/Unit/Transfer/Adapter/HttpTest.php | 4 +++ .../Framework/File/Transfer/Adapter/Http.php | 34 +++++++++++++------ 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Http.php b/lib/internal/Magento/Framework/App/Http.php index 5c436ffdbc149..3564e5e0ecb9b 100644 --- a/lib/internal/Magento/Framework/App/Http.php +++ b/lib/internal/Magento/Framework/App/Http.php @@ -3,17 +3,18 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App; use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Framework\Debug; -use Magento\Framework\ObjectManager\ConfigLoaderInterface; use Magento\Framework\App\Request\Http as RequestHttp; use Magento\Framework\App\Response\Http as ResponseHttp; use Magento\Framework\App\Response\HttpInterface; use Magento\Framework\Controller\ResultInterface; +use Magento\Framework\Debug; use Magento\Framework\Event; use Magento\Framework\Filesystem; +use Magento\Framework\ObjectManager\ConfigLoaderInterface; /** * HTTP web application. Called from webroot index.php to serve web requests. @@ -154,6 +155,7 @@ public function launch() /** * Handle HEAD requests by adding the Content-Length header and removing the body from the response. + * * @return void */ private function handleHeadRequest() @@ -266,7 +268,7 @@ private function redirectToSetup(Bootstrap $bootstrap, \Exception $exception) . "because the Magento setup directory cannot be accessed. \n" . 'You can install Magento using either the command line or you must restore access ' . 'to the following directory: ' . $setupInfo->getDir($projectRoot) . "\n"; - + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception($newMessage, 0, $exception); } } @@ -282,6 +284,7 @@ private function handleBootstrapErrors(Bootstrap $bootstrap, \Exception &$except { $bootstrapCode = $bootstrap->getErrorCode(); if (Bootstrap::ERR_MAINTENANCE == $bootstrapCode) { + // phpcs:ignore Magento2.Security.IncludeFile require $this->_filesystem->getDirectoryRead(DirectoryList::PUB)->getAbsolutePath('errors/503.php'); return true; } @@ -322,6 +325,7 @@ private function handleInitException(\Exception $exception) { if ($exception instanceof \Magento\Framework\Exception\State\InitException) { $this->getLogger()->critical($exception); + // phpcs:ignore Magento2.Security.IncludeFile require $this->_filesystem->getDirectoryRead(DirectoryList::PUB)->getAbsolutePath('errors/404.php'); return true; } @@ -353,6 +357,7 @@ private function handleGenericReport(Bootstrap $bootstrap, \Exception $exception if (isset($params['SCRIPT_NAME'])) { $reportData['script_name'] = $params['SCRIPT_NAME']; } + // phpcs:ignore Magento2.Security.IncludeFile require $this->_filesystem->getDirectoryRead(DirectoryList::PUB)->getAbsolutePath('errors/report.php'); return true; } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php index b2d041ac175f5..48a1242a90d4f 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php @@ -175,6 +175,7 @@ public function testLaunchException() $this->frontControllerMock->expects($this->once())->method('dispatch')->with($this->requestMock)->will( $this->returnCallback( function () { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Message'); } ) @@ -182,7 +183,6 @@ function () { $this->http->launch(); } - /** * Test that HEAD requests lead to an empty body and a Content-Length header matching the original body size. * @dataProvider dataProviderForTestLaunchHeadRequest diff --git a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php index 56375d5178820..92db004ae8e8e 100644 --- a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php +++ b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php @@ -3,10 +3,14 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\File\Test\Unit\Transfer\Adapter; use \Magento\Framework\File\Transfer\Adapter\Http; +/** + * Tests http transfer adapter. + */ class HttpTest extends \PHPUnit\Framework\TestCase { /** diff --git a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php index 386ee0e5bb940..7cafb826f766d 100644 --- a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php +++ b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php @@ -6,9 +6,11 @@ namespace Magento\Framework\File\Transfer\Adapter; +/** + * File adapter to send the file to the client. + */ class Http { - /** * @var \Magento\Framework\HTTP\PhpEnvironment\Response */ @@ -25,7 +27,7 @@ class Http private $request; /** - * @param \Magento\Framework\App\Response\Http $response + * @param \Magento\Framework\HTTP\PhpEnvironment\Response $response * @param \Magento\Framework\File\Mime $mime * @param \Magento\Framework\App\Request\Http|null $request */ @@ -56,14 +58,7 @@ public function send($options = null) throw new \InvalidArgumentException("File '{$filepath}' does not exists."); } - $mimeType = $this->mime->getMimeType($filepath); - if (is_array($options) && isset($options['headers']) && $options['headers'] instanceof \Zend\Http\Headers) { - $this->response->setHeaders($options['headers']); - } - $this->response->setHeader('Content-length', filesize($filepath)); - $this->response->setHeader('Content-Type', $mimeType); - - $this->response->sendHeaders(); + $this->prepareResponse($options, $filepath); if ($this->request->isHead()) { // Do not send the body on HEAD requests. @@ -73,6 +68,7 @@ public function send($options = null) $handle = fopen($filepath, 'r'); if ($handle) { while (($buffer = fgets($handle, 4096)) !== false) { + // phpcs:ignore Magento2.Security.LanguageConstruct.DirectOutput echo $buffer; } if (!feof($handle)) { @@ -103,4 +99,22 @@ private function getFilePath($options): string return $filePath; } + + /** + * Set and send all necessary headers. + * + * @param array $options + * @param string $filepath + */ + protected function prepareResponse($options, string $filepath): void + { + $mimeType = $this->mime->getMimeType($filepath); + if (is_array($options) && isset($options['headers']) && $options['headers'] instanceof \Zend\Http\Headers) { + $this->response->setHeaders($options['headers']); + } + $this->response->setHeader('Content-length', filesize($filepath)); + $this->response->setHeader('Content-Type', $mimeType); + + $this->response->sendHeaders(); + } } From 2d0eecc3e3cab0bd1bf0f2c70d3ff097711d6304 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 3 Apr 2019 15:16:03 +0300 Subject: [PATCH 346/603] graphQl-512: added street lines validation --- .../Model/Cart/QuoteAddress/Validator.php | 45 +++++++++++++ .../Model/Cart/QuoteAddressFactory.php | 14 +++- .../Customer/CreateCustomerAddressTest.php | 66 +++++++++++++++++++ .../Customer/SetBillingAddressOnCartTest.php | 43 ++++++++++++ .../Customer/SetShippingAddressOnCartTest.php | 46 +++++++++++++ .../Guest/SetBillingAddressOnCartTest.php | 43 ++++++++++++ .../Guest/SetShippingAddressOnCartTest.php | 44 +++++++++++++ 7 files changed, 300 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddress/Validator.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddress/Validator.php b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddress/Validator.php new file mode 100644 index 0000000000000..8cf2478d8f8b6 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddress/Validator.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\QuoteGraphQl\Model\Cart\QuoteAddress; + +use Magento\Customer\Helper\Address as AddressHelper; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\Quote\Model\Quote\Address as QuoteAddress; + +/** + * Validate Quote Address + */ +class Validator +{ + /** + * @var AddressHelper + */ + private $addressHelper; + + /** + * @param AddressHelper $addressHelper + */ + public function __construct(AddressHelper $addressHelper) + { + $this->addressHelper = $addressHelper; + } + + /** + * Additional Quote Address validation for the GraphQl endpoint + * + * @param QuoteAddress $quoteAddress + * @throws GraphQlInputException + */ + public function validate(QuoteAddress $quoteAddress) + { + $maxAllowedLineCount = $this->addressHelper->getStreetLines(); + if (is_array($quoteAddress->getStreet()) && count($quoteAddress->getStreet()) > $maxAllowedLineCount) { + throw new GraphQlInputException(__('"Street Address" cannot contain more than %1 lines.', $maxAllowedLineCount)); + } + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php index 76bdc74611131..734843e1be09b 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php @@ -12,6 +12,7 @@ use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Quote\Model\Quote\Address as QuoteAddress; use Magento\Quote\Model\Quote\AddressFactory as BaseQuoteAddressFactory; +use Magento\QuoteGraphQl\Model\Cart\QuoteAddress\Validator; /** * Create QuoteAddress @@ -22,14 +23,21 @@ class QuoteAddressFactory * @var BaseQuoteAddressFactory */ private $quoteAddressFactory; + /** + * @var Validator + */ + private $quoteAddressValidator; /** * @param BaseQuoteAddressFactory $quoteAddressFactory + * @param Validator $quoteAddressValidator */ public function __construct( - BaseQuoteAddressFactory $quoteAddressFactory + BaseQuoteAddressFactory $quoteAddressFactory, + Validator $quoteAddressValidator ) { $this->quoteAddressFactory = $quoteAddressFactory; + $this->quoteAddressValidator = $quoteAddressValidator; } /** @@ -44,6 +52,8 @@ public function createBasedOnInputData(array $addressInput): QuoteAddress $quoteAddress = $this->quoteAddressFactory->create(); $quoteAddress->addData($addressInput); + $this->quoteAddressValidator->validate($quoteAddress); + return $quoteAddress; } @@ -62,6 +72,8 @@ public function createBasedOnCustomerAddress(CustomerAddress $customerAddress): } catch (LocalizedException $e) { throw new GraphQlInputException(__($e->getMessage()), $e); } + $this->quoteAddressValidator->validate($quoteAddress); + return $quoteAddress; } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php index 602d969924fbd..4ea19f08e3c1c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php @@ -198,6 +198,72 @@ public function testCreateCustomerAddressWithMissingAttribute() $this->graphQlQuery($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer_without_addresses.php + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testCreateCustomerAddressWithRedundantStreetLine() + { + $newAddress = [ + 'region' => [ + 'region' => 'Arizona', + 'region_id' => 4, + 'region_code' => 'AZ' + ], + 'country_id' => 'US', + 'street' => ['Line 1 Street', 'Line 2', 'Line 3'], + 'company' => 'Company name', + 'telephone' => '123456789', + 'fax' => '123123123', + 'postcode' => '7777', + 'city' => 'City Name', + 'firstname' => 'Adam', + 'lastname' => 'Phillis', + 'middlename' => 'A', + 'prefix' => 'Mr.', + 'suffix' => 'Jr.', + 'vat_id' => '1', + 'default_shipping' => true, + 'default_billing' => false + ]; + + $mutation + = <<<MUTATION +mutation { + createCustomerAddress(input: { + region: { + region: "{$newAddress['region']['region']}" + region_id: {$newAddress['region']['region_id']} + region_code: "{$newAddress['region']['region_code']}" + } + country_id: {$newAddress['country_id']} + street: ["{$newAddress['street'][0]}","{$newAddress['street'][1]}","{$newAddress['street'][2]}"] + company: "{$newAddress['company']}" + telephone: "{$newAddress['telephone']}" + fax: "{$newAddress['fax']}" + postcode: "{$newAddress['postcode']}" + city: "{$newAddress['city']}" + firstname: "{$newAddress['firstname']}" + lastname: "{$newAddress['lastname']}" + middlename: "{$newAddress['middlename']}" + prefix: "{$newAddress['prefix']}" + suffix: "{$newAddress['suffix']}" + vat_id: "{$newAddress['vat_id']}" + default_shipping: true + default_billing: false + }) { + id + } +} +MUTATION; + + $userName = 'customer@example.com'; + $password = 'password'; + + self::expectExceptionMessage('"Street Address" cannot contain more than 2 lines.'); + $this->graphQlQuery($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); + } + /** * Verify the fields for Customer address * diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php index 88e7b93dd1d08..2ee5bb6708f4c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php @@ -493,6 +493,49 @@ public function testSetBillingAddressWithoutRequiredParameters(string $input, st $this->graphQlQuery($query); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testSetNewBillingAddressWithRedundantStreetLine() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = <<<QUERY +mutation { + setBillingAddressOnCart( + input: { + cart_id: "$maskedQuoteId" + billing_address: { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2", "test street 3"] + city: "test city" + region: "test region" + postcode: "887766" + country_code: "US" + telephone: "88776655" + save_in_address_book: false + } + } + } + ) { + cart { + billing_address { + firstname + } + } + } +} +QUERY; + self::expectExceptionMessage('"Street Address" cannot contain more than 2 lines.'); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + /** * @return array */ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php index 5ff29d20b34d7..f765851f2372e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php @@ -486,6 +486,52 @@ public function testSetMultipleNewShippingAddresses() $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testSetNewShippingAddressOnCartWithRedundantStreetLine() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = <<<QUERY +mutation { + setShippingAddressesOnCart( + input: { + cart_id: "$maskedQuoteId" + shipping_addresses: [ + { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2", "test street 3"] + city: "test city" + region: "test region" + postcode: "887766" + country_code: "US" + telephone: "88776655" + save_in_address_book: false + } + } + ] + } + ) { + cart { + shipping_addresses { + firstname + } + } + } +} +QUERY; + + self::expectExceptionMessage('"Street Address" cannot contain more than 2 lines.'); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + /** * Verify the all the whitelisted fields for a New Address Object * diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php index ae0a1a0e822ac..5fe0ae05903c5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php @@ -313,6 +313,49 @@ public function testSetBillingAddressWithoutRequiredParameters(string $input, st $this->graphQlQuery($query); } + /** + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testSetNewBillingAddressRedundantStreetLine() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = <<<QUERY +mutation { + setBillingAddressOnCart( + input: { + cart_id: "$maskedQuoteId" + billing_address: { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2", "test street 3"] + city: "test city" + region: "test region" + postcode: "887766" + country_code: "US" + telephone: "88776655" + save_in_address_book: false + } + } + } + ) { + cart { + billing_address { + firstname + } + } + } +} +QUERY; + + self::expectExceptionMessage('"Street Address" cannot contain more than 2 lines.'); + $this->graphQlQuery($query); + } + /** * @return array */ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php index e21d9ed64d491..f86b621497200 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php @@ -246,6 +246,50 @@ public function testSetNewShippingAddressWithMissedRequiredParameters(string $in $this->graphQlQuery($query); } + /** + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testSetNewShippingAddressOnCartWithRedundantStreetLine() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = <<<QUERY +mutation { + setShippingAddressesOnCart( + input: { + cart_id: "$maskedQuoteId" + shipping_addresses: [ + { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2", "test street 3"] + city: "test city" + region: "test region" + postcode: "887766" + country_code: "US" + telephone: "88776655" + save_in_address_book: false + } + } + ] + } + ) { + cart { + shipping_addresses { + firstname + } + } + } +} +QUERY; + self::expectExceptionMessage('"Street Address" cannot contain more than 2 lines.'); + $this->graphQlQuery($query); + } + /** * @return array */ From bd04930788146e542ea2b761e4ccc921095cd5c0 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Wed, 3 Apr 2019 16:07:15 +0300 Subject: [PATCH 347/603] Fix static tests. --- .../Framework/Crontab/CrontabManager.php | 17 ++++--- .../Crontab/Test/Unit/CrontabManagerTest.php | 44 ++++++++++--------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/lib/internal/Magento/Framework/Crontab/CrontabManager.php b/lib/internal/Magento/Framework/Crontab/CrontabManager.php index 37ced978c5567..da81540faf477 100644 --- a/lib/internal/Magento/Framework/Crontab/CrontabManager.php +++ b/lib/internal/Magento/Framework/Crontab/CrontabManager.php @@ -4,6 +4,7 @@ * See COPYING.txt for license details. */ + namespace Magento\Framework\Crontab; use Magento\Framework\App\Filesystem\DirectoryList; @@ -40,31 +41,35 @@ public function __construct( } /** + * Build tasks block start text. + * * @return string */ private function getTasksBlockStart() { $tasksBlockStart = self::TASKS_BLOCK_START; if (defined('BP')) { - $tasksBlockStart .= ' ' . md5(BP); + $tasksBlockStart .= ' ' . hash("sha256", BP); } return $tasksBlockStart; } /** + * Build tasks block end text. + * * @return string */ private function getTasksBlockEnd() { $tasksBlockEnd = self::TASKS_BLOCK_END; if (defined('BP')) { - $tasksBlockEnd .= ' ' . md5(BP); + $tasksBlockEnd .= ' ' . hash("sha256", BP); } return $tasksBlockEnd; } /** - * {@inheritdoc} + * @inheritdoc */ public function getTasks() { @@ -82,7 +87,7 @@ public function getTasks() } /** - * {@inheritdoc} + * @inheritdoc */ public function saveTasks(array $tasks) { @@ -118,8 +123,7 @@ public function saveTasks(array $tasks) } /** - * {@inheritdoc} - * @throws LocalizedException + * @inheritdoc */ public function removeTasks() { @@ -203,6 +207,7 @@ private function save($content) try { $this->shell->execute('echo "' . $content . '" | crontab -'); + // phpcs:disable Magento2.Exceptions.ThrowCatch } catch (LocalizedException $e) { throw new LocalizedException( new Phrase('Error during saving of crontab: %1', [$e->getPrevious()->getMessage()]), diff --git a/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php b/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php index b07703d2bd0ba..f6c863d9d9fad 100644 --- a/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php +++ b/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php @@ -4,6 +4,7 @@ * See COPYING.txt for license details. */ + namespace Magento\Framework\Crontab\Test\Unit; use Magento\Framework\Crontab\CrontabManager; @@ -16,6 +17,9 @@ use Magento\Framework\Filesystem\Directory\ReadInterface; use Magento\Framework\Filesystem\DriverPool; +/** + * Tests crontab manager functionality. + */ class CrontabManagerTest extends \PHPUnit\Framework\TestCase { /** @@ -88,17 +92,17 @@ public function getTasksDataProvider() return [ [ 'content' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . hash("sha256", BP) . PHP_EOL . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL, + . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . hash("sha256", BP) . PHP_EOL, 'tasks' => ['* * * * * /bin/php /var/www/magento/bin/magento cron:run'], ], [ 'content' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . hash("sha256", BP) . PHP_EOL . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL . '* * * * * /bin/php /var/www/magento/bin/magento setup:cron:run' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL, + . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . hash("sha256", BP) . PHP_EOL, 'tasks' => [ '* * * * * /bin/php /var/www/magento/bin/magento cron:run', '* * * * * /bin/php /var/www/magento/bin/magento setup:cron:run', @@ -166,17 +170,17 @@ public function removeTasksDataProvider() return [ [ 'contentBefore' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . hash("sha256", BP) . PHP_EOL . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL, + . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . hash("sha256", BP) . PHP_EOL, 'contentAfter' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL ], [ 'contentBefore' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . hash("sha256", BP) . PHP_EOL . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL . '* * * * * /bin/php /var/www/magento/bin/magento setup:cron:run' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL, + . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . hash("sha256", BP) . PHP_EOL, 'contentAfter' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL ], [ @@ -292,9 +296,9 @@ public function testSaveTasks($tasks, $content, $contentToSave) public function saveTasksDataProvider() { $content = '* * * * * /bin/php /var/www/cron.php' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . hash("sha256", BP) . PHP_EOL . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL; + . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . hash("sha256", BP) . PHP_EOL; return [ [ @@ -303,9 +307,9 @@ public function saveTasksDataProvider() ], 'content' => $content, 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . hash("sha256", BP) . PHP_EOL . '* * * * * ' . PHP_BINARY . ' run.php' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL, + . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . hash("sha256", BP) . PHP_EOL, ], [ 'tasks' => [ @@ -313,9 +317,9 @@ public function saveTasksDataProvider() ], 'content' => $content, 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . hash("sha256", BP) . PHP_EOL . '1 2 3 4 5 ' . PHP_BINARY . ' run.php' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL, + . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . hash("sha256", BP) . PHP_EOL, ], [ 'tasks' => [ @@ -323,10 +327,10 @@ public function saveTasksDataProvider() ], 'content' => $content, 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . hash("sha256", BP) . PHP_EOL . '* * * * * ' . PHP_BINARY . ' /var/www/magento2/run.php >>' . ' /var/www/magento2/var/log/cron.log' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL, + . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . hash("sha256", BP) . PHP_EOL, ], [ 'tasks' => [ @@ -334,10 +338,10 @@ public function saveTasksDataProvider() ], 'content' => $content, 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . hash("sha256", BP) . PHP_EOL . '* * * * * ' . PHP_BINARY . ' /var/www/magento2/run.php' . ' %% cron:run | grep -v \"Ran \'jobs\' by schedule\"' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL, + . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . hash("sha256", BP) . PHP_EOL, ], [ 'tasks' => [ @@ -345,10 +349,10 @@ public function saveTasksDataProvider() ], 'content' => '* * * * * /bin/php /var/www/cron.php', 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . hash("sha256", BP) . PHP_EOL . '* * * * * ' . PHP_BINARY . ' /var/www/magento2/run.php' . ' %% cron:run | grep -v \"Ran \'jobs\' by schedule\"' . PHP_EOL - . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL, + . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . hash("sha256", BP) . PHP_EOL, ], ]; } From c998567f363d14a14edba3a6727bfa6effa0350d Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Wed, 3 Apr 2019 16:16:56 +0300 Subject: [PATCH 348/603] MAGETWO-98620: Shipping quote in cart not persisted for Guest customers when Persistent Shopping Cart is enabled --- .../Test/Unit/Observer/SetQuotePersistentDataObserverTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Persistent/Test/Unit/Observer/SetQuotePersistentDataObserverTest.php b/app/code/Magento/Persistent/Test/Unit/Observer/SetQuotePersistentDataObserverTest.php index d74aaa1c90362..ffa829e8456cc 100644 --- a/app/code/Magento/Persistent/Test/Unit/Observer/SetQuotePersistentDataObserverTest.php +++ b/app/code/Magento/Persistent/Test/Unit/Observer/SetQuotePersistentDataObserverTest.php @@ -7,6 +7,9 @@ namespace Magento\Persistent\Test\Unit\Observer; +/** + * Observer test for setting "is_persistent" value to quote + */ class SetQuotePersistentDataObserverTest extends \PHPUnit\Framework\TestCase { /** From 4ce2497fe539dd4357a295ee5f03864a20f6a223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Ca=C3=A7ador?= <samuelmoreira27@gmail.com> Date: Wed, 3 Apr 2019 14:20:41 +0100 Subject: [PATCH 349/603] Fix broken link in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e3cf448f99fb..af1d3d4c80404 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Welcome to Magento 2 installation! We're glad you chose to install Magento 2, a cutting-edge, feature-rich eCommerce solution that gets results. ## Magento System Requirements -[Magento System Requirements](https://devdocs.magento.com/guides/v2.3/install-gde/system-requirements2.html). +[Magento System Requirements](https://devdocs.magento.com/guides/v2.3/install-gde/system-requirements.html). ## Install Magento From c72c82229afd81d0ffbed81fd822c1783e3c8c9b Mon Sep 17 00:00:00 2001 From: Davit_Zakharyan <davit_zakharyan@epam.com> Date: Wed, 3 Apr 2019 17:38:17 +0400 Subject: [PATCH 350/603] MAGETWO-91523: [2.3] Allowed countries restriction for a default website is applied to backend customer grid - Fixed automated test script. --- .../Test/AllowedCountriesRestrictionApplyOnBackendTest.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml index ed353403fc15d..d8d77b6564987 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml @@ -26,16 +26,16 @@ <!--Create new website,store and store view--> <comment userInput="Create new website,store and store view" stepKey="createWebsite"/> <amOnPage url="{{AdminSystemStorePage.url}}" stepKey="goToAdminSystemStorePage"/> - <actionGroup ref="AdminCreateWebsite" stepKey="AdminCreateNewWebsite"> + <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="AdminCreateNewWebsite"> <argument name="newWebsiteName" value="{{NewWebSiteData.name}}"/> <argument name="websiteCode" value="{{NewWebSiteData.code}}"/> </actionGroup> - <actionGroup ref="AdminCreateNewStore" stepKey="AdminCreateNewStore"> + <actionGroup ref="AdminCreateNewStoreGroupActionGroup" stepKey="AdminCreateNewStore"> <argument name="website" value="{{NewWebSiteData.name}}"/> <argument name="storeGroupName" value="{{NewStoreData.name}}"/> <argument name="storeGroupCode" value="{{NewStoreData.code}}"/> </actionGroup> - <actionGroup ref="AdminCreateStoreView" stepKey="AdminCreateNewStoreView"> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="AdminCreateNewStoreView"> <argument name="StoreGroup" value="NewStoreData"/> </actionGroup> <!--Set account sharing option - Default value is 'Per Website'--> From e29fa3d9b150d81da1caa3484d90ecc3d2156770 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Wed, 3 Apr 2019 16:44:50 +0300 Subject: [PATCH 351/603] magento/magento2#18440: Static test fix. --- .../Block/Product/View/GalleryOptions.php | 4 +- .../Block/Product/View/GalleryOptionsTest.php | 446 +++++++++--------- 2 files changed, 226 insertions(+), 224 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php b/app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php index dd2c62174a734..0384c9cd9acce 100644 --- a/app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php +++ b/app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php @@ -3,7 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Catalog\Block\Product\View; use Magento\Framework\View\Element\Block\ArgumentInterface; @@ -11,6 +10,9 @@ use Magento\Catalog\Block\Product\Context; use Magento\Framework\Stdlib\ArrayUtils; +/** + * Gallery options block. + */ class GalleryOptions extends AbstractView implements ArgumentInterface { /** diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/View/GalleryOptionsTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/View/GalleryOptionsTest.php index 5ade6af9fac33..7ed8b13fce750 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Product/View/GalleryOptionsTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/View/GalleryOptionsTest.php @@ -1,223 +1,223 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Catalog\Test\Unit\Block\Product\View; - -use Magento\Catalog\Block\Product\Context; -use Magento\Catalog\Block\Product\View\Gallery; -use Magento\Catalog\Block\Product\View\GalleryOptions; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; -use Magento\Framework\Escaper; -use Magento\Framework\View\Config; -use Magento\Framework\Config\View; -use Magento\Framework\Serialize\Serializer\Json; - -/** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class GalleryOptionsTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var GalleryOptions - */ - private $model; - - /** - * @var Gallery|\PHPUnit_Framework_MockObject_MockObject - */ - private $gallery; - - /** - * @var Context|\PHPUnit_Framework_MockObject_MockObject - */ - private $context; - - /** - * @var Json - */ - private $jsonSerializer; - - /** - * @var View|\PHPUnit_Framework_MockObject_MockObject - */ - private $configView; - - /** - * @var Config|\PHPUnit_Framework_MockObject_MockObject - */ - private $viewConfig; - - /** - * @var Escaper - */ - private $escaper; - - protected function setUp() - { - $objectManager = new ObjectManager($this); - - $this->escaper = $objectManager->getObject(Escaper::class); - $this->configView = $this->createMock(View::class); - - $this->viewConfig = $this->createConfiguredMock( - Config::class, - [ - 'getViewConfig' => $this->configView - ] - ); - - $this->context = $this->createConfiguredMock( - Context::class, - [ - 'getEscaper' => $this->escaper, - 'getViewConfig' => $this->viewConfig - ] - ); - - $this->gallery = $this->createMock(Gallery::class); - - $this->jsonSerializer = $objectManager->getObject( - Json::class - ); - - $this->model = $objectManager->getObject(GalleryOptions::class, [ - 'context' => $this->context, - 'jsonSerializer' => $this->jsonSerializer, - 'gallery' => $this->gallery - ]); - } - - public function testGetOptionsJson() - { - $configMap = [ - ['Magento_Catalog', 'gallery/nav', 'thumbs'], - ['Magento_Catalog', 'gallery/loop', false], - ['Magento_Catalog', 'gallery/keyboard', true], - ['Magento_Catalog', 'gallery/arrows', true], - ['Magento_Catalog', 'gallery/caption', false], - ['Magento_Catalog', 'gallery/allowfullscreen', true], - ['Magento_Catalog', 'gallery/navdir', 'horizontal'], - ['Magento_Catalog', 'gallery/navarrows', true], - ['Magento_Catalog', 'gallery/navtype', 'slides'], - ['Magento_Catalog', 'gallery/thumbmargin', '5'], - ['Magento_Catalog', 'gallery/transition/effect', 'slide'], - ['Magento_Catalog', 'gallery/transition/duration', '500'], - ]; - - $imageAttributesMap = [ - ['product_page_image_medium','height',null, 100], - ['product_page_image_medium','width',null, 200], - ['product_page_image_small','height',null, 300], - ['product_page_image_small','width',null, 400] - ]; - - $this->configView->expects($this->any()) - ->method('getVarValue') - ->will($this->returnValueMap($configMap)); - $this->gallery->expects($this->any()) - ->method('getImageAttribute') - ->will($this->returnValueMap($imageAttributesMap)); - - $json = $this->model->getOptionsJson(); - - $decodedJson = $this->jsonSerializer->unserialize($json); - - $this->assertSame('thumbs', $decodedJson['nav']); - $this->assertSame(false, $decodedJson['loop']); - $this->assertSame(true, $decodedJson['keyboard']); - $this->assertSame(true, $decodedJson['arrows']); - $this->assertSame(false, $decodedJson['showCaption']); - $this->assertSame(true, $decodedJson['allowfullscreen']); - $this->assertSame('horizontal', $decodedJson['navdir']); - $this->assertSame(true, $decodedJson['navarrows']); - $this->assertSame('slides', $decodedJson['navtype']); - $this->assertSame(5, $decodedJson['thumbmargin']); - $this->assertSame('slide', $decodedJson['transition']); - $this->assertSame(500, $decodedJson['transitionduration']); - $this->assertSame(100, $decodedJson['height']); - $this->assertSame(200, $decodedJson['width']); - $this->assertSame(300, $decodedJson['thumbheight']); - $this->assertSame(400, $decodedJson['thumbwidth']); - } - - public function testGetFSOptionsJson() - { - $configMap = [ - ['Magento_Catalog', 'gallery/fullscreen/nav', false], - ['Magento_Catalog', 'gallery/fullscreen/loop', true], - ['Magento_Catalog', 'gallery/fullscreen/keyboard', true], - ['Magento_Catalog', 'gallery/fullscreen/arrows', false], - ['Magento_Catalog', 'gallery/fullscreen/caption', true], - ['Magento_Catalog', 'gallery/fullscreen/navdir', 'vertical'], - ['Magento_Catalog', 'gallery/fullscreen/navarrows', false], - ['Magento_Catalog', 'gallery/fullscreen/navtype', 'thumbs'], - ['Magento_Catalog', 'gallery/fullscreen/thumbmargin', '10'], - ['Magento_Catalog', 'gallery/fullscreen/transition/effect', 'dissolve'], - ['Magento_Catalog', 'gallery/fullscreen/transition/duration', '300'] - ]; - - $this->configView->expects($this->any()) - ->method('getVarValue') - ->will($this->returnValueMap($configMap)); - - $json = $this->model->getFSOptionsJson(); - - $decodedJson = $this->jsonSerializer->unserialize($json); - - //Note, this tests the special case for nav variable set to false. It - //Should not be converted to boolean. - $this->assertSame('false', $decodedJson['nav']); - $this->assertSame(true, $decodedJson['loop']); - $this->assertSame(false, $decodedJson['arrows']); - $this->assertSame(true, $decodedJson['keyboard']); - $this->assertSame(true, $decodedJson['showCaption']); - $this->assertSame('vertical', $decodedJson['navdir']); - $this->assertSame(false, $decodedJson['navarrows']); - $this->assertSame(10, $decodedJson['thumbmargin']); - $this->assertSame('thumbs', $decodedJson['navtype']); - $this->assertSame('dissolve', $decodedJson['transition']); - $this->assertSame(300, $decodedJson['transitionduration']); - } - - public function testGetOptionsJsonOptionals() - { - $configMap = [ - ['Magento_Catalog', 'gallery/fullscreen/thumbmargin', false], - ['Magento_Catalog', 'gallery/fullscreen/transition/duration', false] - ]; - - $this->configView->expects($this->any()) - ->method('getVarValue') - ->will($this->returnValueMap($configMap)); - - $json = $this->model->getOptionsJson(); - - $decodedJson = $this->jsonSerializer->unserialize($json); - - $this->assertArrayNotHasKey('thumbmargin', $decodedJson); - $this->assertArrayNotHasKey('transitionduration', $decodedJson); - } - - public function testGetFSOptionsJsonOptionals() - { - $configMap = [ - ['Magento_Catalog', 'gallery/fullscreen/keyboard', false], - ['Magento_Catalog', 'gallery/fullscreen/thumbmargin', false], - ['Magento_Catalog', 'gallery/fullscreen/transition/duration', false] - ]; - - $this->configView->expects($this->any()) - ->method('getVarValue') - ->will($this->returnValueMap($configMap)); - - $json = $this->model->getFSOptionsJson(); - - $decodedJson = $this->jsonSerializer->unserialize($json); - - $this->assertArrayNotHasKey('thumbmargin', $decodedJson); - $this->assertArrayNotHasKey('keyboard', $decodedJson); - $this->assertArrayNotHasKey('transitionduration', $decodedJson); - } -} +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Test\Unit\Block\Product\View; + +use Magento\Catalog\Block\Product\Context; +use Magento\Catalog\Block\Product\View\Gallery; +use Magento\Catalog\Block\Product\View\GalleryOptions; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Escaper; +use Magento\Framework\View\Config; +use Magento\Framework\Config\View; +use Magento\Framework\Serialize\Serializer\Json; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class GalleryOptionsTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var GalleryOptions + */ + private $model; + + /** + * @var Gallery|\PHPUnit_Framework_MockObject_MockObject + */ + private $gallery; + + /** + * @var Context|\PHPUnit_Framework_MockObject_MockObject + */ + private $context; + + /** + * @var Json + */ + private $jsonSerializer; + + /** + * @var View|\PHPUnit_Framework_MockObject_MockObject + */ + private $configView; + + /** + * @var Config|\PHPUnit_Framework_MockObject_MockObject + */ + private $viewConfig; + + /** + * @var Escaper + */ + private $escaper; + + protected function setUp() + { + $objectManager = new ObjectManager($this); + + $this->escaper = $objectManager->getObject(Escaper::class); + $this->configView = $this->createMock(View::class); + + $this->viewConfig = $this->createConfiguredMock( + Config::class, + [ + 'getViewConfig' => $this->configView + ] + ); + + $this->context = $this->createConfiguredMock( + Context::class, + [ + 'getEscaper' => $this->escaper, + 'getViewConfig' => $this->viewConfig + ] + ); + + $this->gallery = $this->createMock(Gallery::class); + + $this->jsonSerializer = $objectManager->getObject( + Json::class + ); + + $this->model = $objectManager->getObject(GalleryOptions::class, [ + 'context' => $this->context, + 'jsonSerializer' => $this->jsonSerializer, + 'gallery' => $this->gallery + ]); + } + + public function testGetOptionsJson() + { + $configMap = [ + ['Magento_Catalog', 'gallery/nav', 'thumbs'], + ['Magento_Catalog', 'gallery/loop', false], + ['Magento_Catalog', 'gallery/keyboard', true], + ['Magento_Catalog', 'gallery/arrows', true], + ['Magento_Catalog', 'gallery/caption', false], + ['Magento_Catalog', 'gallery/allowfullscreen', true], + ['Magento_Catalog', 'gallery/navdir', 'horizontal'], + ['Magento_Catalog', 'gallery/navarrows', true], + ['Magento_Catalog', 'gallery/navtype', 'slides'], + ['Magento_Catalog', 'gallery/thumbmargin', '5'], + ['Magento_Catalog', 'gallery/transition/effect', 'slide'], + ['Magento_Catalog', 'gallery/transition/duration', '500'], + ]; + + $imageAttributesMap = [ + ['product_page_image_medium','height',null, 100], + ['product_page_image_medium','width',null, 200], + ['product_page_image_small','height',null, 300], + ['product_page_image_small','width',null, 400] + ]; + + $this->configView->expects($this->any()) + ->method('getVarValue') + ->will($this->returnValueMap($configMap)); + $this->gallery->expects($this->any()) + ->method('getImageAttribute') + ->will($this->returnValueMap($imageAttributesMap)); + + $json = $this->model->getOptionsJson(); + + $decodedJson = $this->jsonSerializer->unserialize($json); + + $this->assertSame('thumbs', $decodedJson['nav']); + $this->assertSame(false, $decodedJson['loop']); + $this->assertSame(true, $decodedJson['keyboard']); + $this->assertSame(true, $decodedJson['arrows']); + $this->assertSame(false, $decodedJson['showCaption']); + $this->assertSame(true, $decodedJson['allowfullscreen']); + $this->assertSame('horizontal', $decodedJson['navdir']); + $this->assertSame(true, $decodedJson['navarrows']); + $this->assertSame('slides', $decodedJson['navtype']); + $this->assertSame(5, $decodedJson['thumbmargin']); + $this->assertSame('slide', $decodedJson['transition']); + $this->assertSame(500, $decodedJson['transitionduration']); + $this->assertSame(100, $decodedJson['height']); + $this->assertSame(200, $decodedJson['width']); + $this->assertSame(300, $decodedJson['thumbheight']); + $this->assertSame(400, $decodedJson['thumbwidth']); + } + + public function testGetFSOptionsJson() + { + $configMap = [ + ['Magento_Catalog', 'gallery/fullscreen/nav', false], + ['Magento_Catalog', 'gallery/fullscreen/loop', true], + ['Magento_Catalog', 'gallery/fullscreen/keyboard', true], + ['Magento_Catalog', 'gallery/fullscreen/arrows', false], + ['Magento_Catalog', 'gallery/fullscreen/caption', true], + ['Magento_Catalog', 'gallery/fullscreen/navdir', 'vertical'], + ['Magento_Catalog', 'gallery/fullscreen/navarrows', false], + ['Magento_Catalog', 'gallery/fullscreen/navtype', 'thumbs'], + ['Magento_Catalog', 'gallery/fullscreen/thumbmargin', '10'], + ['Magento_Catalog', 'gallery/fullscreen/transition/effect', 'dissolve'], + ['Magento_Catalog', 'gallery/fullscreen/transition/duration', '300'] + ]; + + $this->configView->expects($this->any()) + ->method('getVarValue') + ->will($this->returnValueMap($configMap)); + + $json = $this->model->getFSOptionsJson(); + + $decodedJson = $this->jsonSerializer->unserialize($json); + + //Note, this tests the special case for nav variable set to false. It + //Should not be converted to boolean. + $this->assertSame('false', $decodedJson['nav']); + $this->assertSame(true, $decodedJson['loop']); + $this->assertSame(false, $decodedJson['arrows']); + $this->assertSame(true, $decodedJson['keyboard']); + $this->assertSame(true, $decodedJson['showCaption']); + $this->assertSame('vertical', $decodedJson['navdir']); + $this->assertSame(false, $decodedJson['navarrows']); + $this->assertSame(10, $decodedJson['thumbmargin']); + $this->assertSame('thumbs', $decodedJson['navtype']); + $this->assertSame('dissolve', $decodedJson['transition']); + $this->assertSame(300, $decodedJson['transitionduration']); + } + + public function testGetOptionsJsonOptionals() + { + $configMap = [ + ['Magento_Catalog', 'gallery/fullscreen/thumbmargin', false], + ['Magento_Catalog', 'gallery/fullscreen/transition/duration', false] + ]; + + $this->configView->expects($this->any()) + ->method('getVarValue') + ->will($this->returnValueMap($configMap)); + + $json = $this->model->getOptionsJson(); + + $decodedJson = $this->jsonSerializer->unserialize($json); + + $this->assertArrayNotHasKey('thumbmargin', $decodedJson); + $this->assertArrayNotHasKey('transitionduration', $decodedJson); + } + + public function testGetFSOptionsJsonOptionals() + { + $configMap = [ + ['Magento_Catalog', 'gallery/fullscreen/keyboard', false], + ['Magento_Catalog', 'gallery/fullscreen/thumbmargin', false], + ['Magento_Catalog', 'gallery/fullscreen/transition/duration', false] + ]; + + $this->configView->expects($this->any()) + ->method('getVarValue') + ->will($this->returnValueMap($configMap)); + + $json = $this->model->getFSOptionsJson(); + + $decodedJson = $this->jsonSerializer->unserialize($json); + + $this->assertArrayNotHasKey('thumbmargin', $decodedJson); + $this->assertArrayNotHasKey('keyboard', $decodedJson); + $this->assertArrayNotHasKey('transitionduration', $decodedJson); + } +} From 6d99e19ec8ea9463d674606bd3b081a4c4b44739 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Wed, 3 Apr 2019 16:17:16 +0200 Subject: [PATCH 352/603] Tests refactoring --- .../Magento/Catalog/_files/product_simple_with_options.php | 4 ++-- .../Catalog/_files/product_simple_with_options_rollback.php | 4 +++- .../testsuite/Magento/Catalog/_files/product_virtual.php | 2 +- .../Magento/Catalog/_files/product_virtual_with_options.php | 2 +- .../Catalog/_files/product_virtual_with_options_rollback.php | 3 ++- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options.php index b139f6865a2f4..fa8046fef3975 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options.php @@ -89,7 +89,7 @@ $customOptions = []; /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */ -$customOptionFactory = $objectManager->create(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); +$customOptionFactory = $objectManager->get(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); foreach ($options as $option) { /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterface $customOption */ @@ -102,5 +102,5 @@ $product->setOptions($customOptions); /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepositoryFactory */ -$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); +$productRepository = $objectManager->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); $productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options_rollback.php index 386e98ceedec4..2d783a6d07522 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options_rollback.php @@ -15,9 +15,11 @@ ); try { $product = $repository->get('simple', false, null, true); - $product->delete(); + $repository->delete($product); } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { //Entity already deleted +} catch (\Magento\Framework\Exception\StateException $e) { + } $registry->unregister('isSecureArea'); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php index d9db7b72a7a13..8f42436f08a31 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php @@ -28,5 +28,5 @@ ] ); /** @var ProductResource $productResource */ -$productResource = Bootstrap::getObjectManager()->create(ProductResource::class); +$productResource = Bootstrap::getObjectManager()->get(ProductResource::class); $productResource->save($product); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options.php index eb215df02b35e..c07eb0f35b0fd 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options.php @@ -89,7 +89,7 @@ $customOptions = []; /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */ -$customOptionFactory = $objectManager->create(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); +$customOptionFactory = $objectManager->get(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); foreach ($options as $option) { /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterface $customOption */ diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options_rollback.php index 0e9b9c4697bdd..070e2890df413 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options_rollback.php @@ -15,9 +15,10 @@ ); try { $product = $repository->get('virtual', false, null, true); - $product->delete(); + $repository->delete($product); } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { //Entity already deleted +} catch (\Magento\Framework\Exception\StateException $e) { } $registry->unregister('isSecureArea'); From ed0dd32d536f0c0da85acbfa057fac796b7b6954 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Wed, 3 Apr 2019 15:40:17 +0200 Subject: [PATCH 353/603] [Checkout coverage] setGuestEmailOnCart mutation --- .../Model/Resolver/GuestEmail.php | 49 +++++++++ .../Model/Resolver/SetGuestEmailOnCart.php | 89 +++++++++++++++ .../Magento/QuoteGraphQl/etc/schema.graphqls | 11 ++ .../Customer/SetGuestEmailOnCartTest.php | 85 +++++++++++++++ .../Quote/Guest/CartGuestEmailTest.php | 52 +++++++++ .../Quote/Guest/SetGuestEmailOnCartTest.php | 101 ++++++++++++++++++ .../quote_with_virtual_product_saved.php | 1 + 7 files changed, 388 insertions(+) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/GuestEmail.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetGuestEmailOnCartTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartGuestEmailTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetGuestEmailOnCartTest.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/GuestEmail.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/GuestEmail.php new file mode 100644 index 0000000000000..76493c4cebe55 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/GuestEmail.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\QuoteGraphQl\Model\Resolver; + +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\GraphQl\Config\Element\Field; +use Magento\Framework\GraphQl\Query\ResolverInterface; +use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; +use Magento\Quote\Model\Quote; +use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; + +/** + * @inheritdoc + */ +class GuestEmail implements ResolverInterface +{ + /** + * @var GetCartForUser + */ + private $getCartForUser; + + /** + * @param GetCartForUser $getCartForUser + */ + public function __construct( + GetCartForUser $getCartForUser + ) { + $this->getCartForUser = $getCartForUser; + } + + /** + * @inheritdoc + */ + public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) + { + if (!isset($value['model'])) { + throw new LocalizedException(__('"model" value should be specified')); + } + /** @var Quote $cart */ + $cart = $value['model']; + + return $cart->getCustomerEmail(); + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php new file mode 100644 index 0000000000000..29dc0e759242f --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php @@ -0,0 +1,89 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\QuoteGraphQl\Model\Resolver; + +use Magento\Framework\Exception\CouldNotSaveException; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\GraphQl\Config\Element\Field; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\Framework\GraphQl\Query\ResolverInterface; +use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; +use Magento\Framework\Validator\EmailAddress as EmailAddressValidator; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; + +/** + * @inheritdoc + */ +class SetGuestEmailOnCart implements ResolverInterface +{ + /** + * @var CartRepositoryInterface + */ + private $cartRepository; + + /** + * @var GetCartForUser + */ + private $getCartForUser; + + /** + * @param GetCartForUser $getCartForUser + * @param CartRepositoryInterface $cartRepository + */ + public function __construct( + GetCartForUser $getCartForUser, + CartRepositoryInterface $cartRepository + ) { + $this->getCartForUser = $getCartForUser; + $this->cartRepository = $cartRepository; + } + + /** + * @inheritdoc + */ + public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) + { + if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) { + throw new GraphQlInputException(__('Required parameter "cart_id" is missing')); + } + $maskedCartId = $args['input']['cart_id']; + + if (!isset($args['input']['email']) || empty($args['input']['email'])) { + throw new GraphQlInputException(__('Required parameter "email" is missing')); + } + + $guestEmail = $args['input']['email']; + + if (!\Zend_Validate::is($guestEmail, EmailAddressValidator::class)) { + throw new GraphQlInputException(__('Invalid email format')); + } + + $currentUserId = $context->getUserId(); + + if ($currentUserId !== 0) { + throw new GraphQlInputException(__('The request is not allowed for logged in customers')); + } + + $cart = $this->getCartForUser->execute($maskedCartId, $currentUserId); + $cart->setCustomerEmail($guestEmail); + + try { + $this->cartRepository->save($cart); + } catch (CouldNotSaveException $e) { + throw new LocalizedException(__($e->getMessage()), $e); + } + + return [ + 'cart' => [ + 'model' => $cart, + 'guest_email' => $guestEmail + ], + ]; + } +} diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 79cea3855f6f3..bf0d1cfb079cd 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -17,6 +17,7 @@ type Mutation { setBillingAddressOnCart(input: SetBillingAddressOnCartInput): SetBillingAddressOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetBillingAddressOnCart") setShippingMethodsOnCart(input: SetShippingMethodsOnCartInput): SetShippingMethodsOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetShippingMethodsOnCart") setPaymentMethodOnCart(input: SetPaymentMethodOnCartInput): SetPaymentMethodOnCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\SetPaymentMethodOnCart") + setGuestEmailOnCart(input: SetGuestEmailOnCartInput): SetGuestEmailOnCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\SetGuestEmailOnCart") } input AddSimpleProductsToCartInput { @@ -124,6 +125,11 @@ input PaymentMethodInput { purchase_order_number: String @doc(description:"Purchase order number") } +input SetGuestEmailOnCartInput { + cart_id: String! + email: String! +} + type SetPaymentMethodOnCartOutput { cart: Cart! } @@ -147,6 +153,7 @@ type ApplyCouponToCartOutput { type Cart { items: [CartItemInterface] @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartItems") applied_coupon: AppliedCoupon @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\AppliedCoupon") + guest_email: String @resolver (class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\GuestEmail") shipping_addresses: [CartAddress]! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddresses") billing_address: CartAddress! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\BillingAddress") available_payment_methods: [AvailablePaymentMethod] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AvailablePaymentMethods") @doc(description: "Available payment methods") @@ -249,6 +256,10 @@ type RemoveItemFromCartOutput { cart: Cart! } +type SetGuestEmailOnCartOutput { + cart: Cart! +} + type SimpleCartItem implements CartItemInterface @doc(description: "Simple Cart Item") { customizable_options: [SelectedCustomizableOption] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\CustomizableOptions") } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetGuestEmailOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetGuestEmailOnCartTest.php new file mode 100644 index 0000000000000..4dca82118c1ef --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetGuestEmailOnCartTest.php @@ -0,0 +1,85 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for setGuestEmailOnCart mutation + */ +class SetGuestEmailOnCartTest extends GraphQlAbstract +{ + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php + */ + public function testSetGuestEmailOnCartForLoggedInCustomer() + { + $reservedOrderId = 'test_order_1'; + $email = 'some@user.com'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + + $query = $this->getSetGuestEmailOnCartMutation($maskedQuoteId, $email); + $this->expectExceptionMessage('The request is not allowed for logged in customers'); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * Returns GraphQl mutation query for setting email address for a guest + * + * @param string $maskedQuoteId + * @param string $email + * @return string + */ + private function getSetGuestEmailOnCartMutation(string $maskedQuoteId, string $email): string + { + return <<<QUERY +mutation { + setGuestEmailOnCart(input: { + cart_id:"$maskedQuoteId" + email: "$email" + }) { + cart { + guest_email + } + } +} +QUERY; + } + + /** + * @param string $username + * @param string $password + * @return array + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartGuestEmailTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartGuestEmailTest.php new file mode 100644 index 0000000000000..751029e6b87a3 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartGuestEmailTest.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for getting guest email from cart + */ +class CartGuestEmailTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php + */ + public function testGetCartGuestEmail() + { + $email = 'store@example.com'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute( + 'test_order_with_virtual_product_without_address' + ); + + $query = <<<QUERY +{ + cart(cart_id:"$maskedQuoteId") { + guest_email + } +} +QUERY; + + $response = $this->graphQlQuery($query); + $this->assertArrayHasKey('cart', $response); + $this->assertEquals($email, $response['cart']['guest_email']); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetGuestEmailOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetGuestEmailOnCartTest.php new file mode 100644 index 0000000000000..f95679b2eb5e1 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetGuestEmailOnCartTest.php @@ -0,0 +1,101 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for setGuestEmailOnCart mutation + */ +class SetGuestEmailOnCartTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/Quote/_files/empty_quote.php + */ + public function testSetGuestEmailOnCart() + { + $reservedOrderId = 'reserved_order_id'; + $email = 'some@user.com'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + + $query = $this->getSetGuestEmailOnCartMutation($maskedQuoteId, $email); + $response = $this->graphQlQuery($query); + + $this->assertArrayHasKey('setGuestEmailOnCart', $response); + $this->assertArrayHasKey('cart', $response['setGuestEmailOnCart']); + $this->assertEquals($email, $response['setGuestEmailOnCart']['cart']['guest_email']); + } + + /** + * @magentoApiDataFixture Magento/Quote/_files/empty_quote.php + * @dataProvider incorrectInputDataProvider + * @param string|null $maskedQuoteId + * @param string $email + * @param string $exceptionMessage + */ + public function testSetGuestEmailOnCartWithIncorrectInputData( + ?string $maskedQuoteId, + string $email, + string $exceptionMessage + ) { + if (null === $maskedQuoteId) { // Generate ID in case if no provided by data provider + $reservedOrderId = 'reserved_order_id'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + } + + $query = $this->getSetGuestEmailOnCartMutation($maskedQuoteId, $email); + $this->expectExceptionMessage($exceptionMessage); + $this->graphQlQuery($query); + } + + public function incorrectInputDataProvider(): array + { + return [ + 'wrong_email' => [null, 'some', 'Invalid email format'], + 'no_email' => [null, '', 'Required parameter "email" is missing'], + 'wrong_quote_id' => ['xxx', 'some@user.com', 'Could not find a cart with ID "xxx"'], + 'no_quote_id' => ['', 'some@user.com', 'Required parameter "cart_id" is missing'] + ]; + } + + /** + * Returns GraphQl mutation query for setting email address for a guest + * + * @param string $maskedQuoteId + * @param string $email + * @return string + */ + private function getSetGuestEmailOnCartMutation(string $maskedQuoteId, string $email): string + { + return <<<QUERY +mutation { + setGuestEmailOnCart(input: { + cart_id:"$maskedQuoteId" + email: "$email" + }) { + cart { + guest_email + } + } +} +QUERY; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_virtual_product_saved.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_virtual_product_saved.php index 835b2ab812856..833e5a57ac34f 100644 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_virtual_product_saved.php +++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_virtual_product_saved.php @@ -13,6 +13,7 @@ ->setIsMultiShipping(false) ->setReservedOrderId('test_order_with_virtual_product_without_address') ->setEmail('store@example.com') + ->setCustomerEmail('store@example.com') ->addProduct( $product->load($product->getId()), 1 From 5868de47f41b90c657b82ebe398b5dcaf9415127 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Wed, 3 Apr 2019 12:41:03 -0500 Subject: [PATCH 354/603] MAGETWO-98831: The SKU was not found in the catalog --- .../Adminhtml/Order/Create/Search/Grid.php | 17 +---------------- .../Grid/DataProvider/ProductCollection.php | 1 - 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid.php index 5b7c1dee65c39..9a271f741edda 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid.php @@ -15,6 +15,7 @@ * @api * @author Magento Core Team <core@magentocommerce.com> * @since 100.0.2 + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Grid extends \Magento\Backend\Block\Widget\Grid\Extended { @@ -167,22 +168,6 @@ protected function _prepareCollection() $this->_salesConfig->getAvailableProductTypes() ); - /* - $collection = $this->_productFactory->create()->getCollection(); - $collection->setStore( - $this->getStore() - )->addAttributeToSelect( - $attributes - )->addAttributeToSelect( - 'sku' - )->addStoreFilter()->addAttributeToFilter( - 'type_id', - $this->_salesConfig->getAvailableProductTypes() - )->addAttributeToSelect( - 'gift_message_available' - ); - */ - $this->setCollection($collection); return parent::_prepareCollection(); } diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid/DataProvider/ProductCollection.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid/DataProvider/ProductCollection.php index 61f30de3a1c51..733791a2f9549 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid/DataProvider/ProductCollection.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Search/Grid/DataProvider/ProductCollection.php @@ -53,4 +53,3 @@ public function getCollectionForStore(Store $store):Collection return $collection; } } - From 61b4ec8ab1638fef820d5ec7125bba886f2b1016 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 3 Apr 2019 12:42:57 -0500 Subject: [PATCH 355/603] GraphQL-295: [Place order] Place order mutation --- .../Model/Resolver/PlaceOrder.php | 19 +- .../GetAvailablePaymentMethodsTest.php | 8 +- .../GetAvailableShippingMethodsTest.php | 8 +- .../GraphQl/Quote/Customer/GetCartTest.php | 2 +- .../GetSelectedShippingMethodTest.php | 8 +- .../GetSpecifiedBillingAddressTest.php | 8 +- .../GraphQl/Quote/Customer/PlaceOrderTest.php | 256 ++++++++++++++++++ .../Customer/SetBillingAddressOnCartTest.php | 14 +- .../SetOfflineShippingMethodsOnCartTest.php | 2 +- .../Customer/SetPaymentMethodOnCartTest.php | 14 +- .../Customer/SetShippingAddressOnCartTest.php | 12 +- .../Customer/SetShippingMethodsOnCartTest.php | 14 +- .../Guest/GetAvailablePaymentMethodsTest.php | 6 +- .../Guest/GetAvailableShippingMethodsTest.php | 6 +- .../GraphQl/Quote/Guest/GetCartTest.php | 2 +- .../Guest/GetSelectedShippingMethodTest.php | 6 +- .../Guest/GetSpecifiedBillingAddressTest.php | 6 +- .../Guest/SetBillingAddressOnCartTest.php | 8 +- .../SetOfflineShippingMethodsOnCartTest.php | 2 +- .../Guest/SetPaymentMethodOnCartTest.php | 12 +- .../Guest/SetShippingAddressOnCartTest.php | 10 +- .../Guest/SetShippingMethodsOnCartTest.php | 14 +- .../Magento/GraphQl/Quote/PlaceOrderTest.php | 224 --------------- .../set_simple_product_out_of_stock.php | 19 ++ .../GraphQl/Catalog/_files/simple_product.php | 45 +++ .../_files/simple_product_rollback.php | 31 +++ .../Quote/_files/add_simple_product.php | 2 +- 27 files changed, 443 insertions(+), 315 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php delete mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/PlaceOrderTest.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/set_simple_product_out_of_stock.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/simple_product.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/simple_product_rollback.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php index c087e867a342a..3bd46a664f2ab 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php @@ -8,8 +8,10 @@ namespace Magento\QuoteGraphQl\Model\Resolver; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Api\CartManagementInterface; @@ -56,13 +58,12 @@ public function __construct( */ public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { - if (!isset($args['input']['cart_id'])) { + if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) { throw new GraphQlInputException(__('Required parameter "cart_id" is missing')); } $maskedCartId = $args['input']['cart_id']; - $currentUserId = $context->getUserId(); - $cart = $this->getCartForUser->execute($maskedCartId, $currentUserId); + $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); try { $orderId = $this->cartManagement->placeOrder($cart->getId()); @@ -70,13 +71,13 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value return [ 'order' => [ - 'order_id' => $order->getIncrementId() - ] + 'order_id' => $order->getIncrementId(), + ], ]; - } catch (LocalizedException $exception) { - throw new GraphQlInputException( - __('Unable to place order: %message', ['message' => $exception->getMessage()]) - ); + } catch (NoSuchEntityException $e) { + throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); + } catch (LocalizedException $e) { + throw new GraphQlInputException(__('Unable to place order: %message', ['message' => $e->getMessage()]), $e); } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailablePaymentMethodsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailablePaymentMethodsTest.php index ba640bc3402ba..673d496302662 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailablePaymentMethodsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailablePaymentMethodsTest.php @@ -39,7 +39,7 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -60,7 +60,7 @@ public function testGetAvailablePaymentMethods() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -79,7 +79,7 @@ public function testGetAvailablePaymentMethodsFromGuestCart() /** * _security * @magentoApiDataFixture Magento/Customer/_files/three_customers.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -97,7 +97,7 @@ public function testGetAvailablePaymentMethodsFromAnotherCustomerCart() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php index 71cf0201951a3..2b647f61c4c63 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php @@ -41,7 +41,7 @@ protected function setUp() * Test case: get available shipping methods from current customer quote * * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -77,7 +77,7 @@ public function testGetAvailableShippingMethods() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -98,7 +98,7 @@ public function testGetAvailableShippingMethodsFromGuestCart() * * _security * @magentoApiDataFixture Magento/Customer/_files/three_customers.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -118,7 +118,7 @@ public function testGetAvailableShippingMethodsFromAnotherCustomerCart() * Test case: get available shipping methods when all shipping methods are disabled * * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php index eb62b8c92f310..b1a58d818016e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php @@ -36,7 +36,7 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/Catalog/_files/product_virtual.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php index 16d085c1d09be..ba169d7a5bbc9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php @@ -39,7 +39,7 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -69,7 +69,7 @@ public function testGetSelectedShippingMethod() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -89,7 +89,7 @@ public function testGetSelectedShippingMethodFromGuestCart() /** * _security * @magentoApiDataFixture Magento/Customer/_files/three_customers.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -108,7 +108,7 @@ public function testGetSelectedShippingMethodFromAnotherCustomerCart() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php index 4396f5fbac189..1ba94346073db 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php @@ -39,7 +39,7 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php @@ -79,7 +79,7 @@ public function testGeSpecifiedBillingAddress() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -132,7 +132,7 @@ public function testGeSpecifiedBillingAddressOfNonExistentCart() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php @@ -150,7 +150,7 @@ public function testGeSpecifiedBillingAddressFromAnotherGuestCart() /** * _security * @magentoApiDataFixture Magento/Customer/_files/three_customers.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php new file mode 100644 index 0000000000000..7ec1a71111835 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php @@ -0,0 +1,256 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for placing an order for customer + */ +class PlaceOrderTest extends GraphQlAbstract +{ + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testPlaceOrder() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('placeOrder', $response); + self::assertArrayHasKey('order_id', $response['placeOrder']['order']); + self::assertEquals($reservedOrderId, $response['placeOrder']['order']['order_id']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testPlaceOrderWithNoItemsInCart() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessage( + 'Unable to place order: A server error stopped your order from being placed. ' . + 'Please try to place your order again' + ); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testPlaceOrderWithNoShippingAddress() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessage( + 'Unable to place order: Some addresses can\'t be used due to the configurations for specific countries' + ); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testPlaceOrderWithNoShippingMethod() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessage( + 'Unable to place order: The shipping method is missing. Select the shipping method and try again' + ); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php + */ + public function testPlaceOrderWithNoBillingAddress() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessageRegExp( + '/Unable to place order: Please check the billing address information*/' + ); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php + */ + public function testPlaceOrderWithNoPaymentMethod() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessage('Unable to place order: Enter a valid payment method and try again'); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/set_simple_product_out_of_stock.php + */ + public function testPlaceOrderWithOutOfStockProduct() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessage('Unable to place order: Some of the products are out of stock'); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testPlaceOrderOfGuestCart() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessageRegExp('/The current user cannot perform operations on cart*/'); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testPlaceOrderOfAnotherCustomerCart() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessageRegExp('/The current user cannot perform operations on cart*/'); + $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer3@search.example.com')); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +mutation { + placeOrder(input: {cart_id: "{$maskedQuoteId}"}) { + order { + order_id + } + } +} +QUERY; + } + + /** + * @param string $username + * @param string $password + * @return array + * @throws \Magento\Framework\Exception\AuthenticationException + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php index 88e7b93dd1d08..ea58ddfcbf5c1 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php @@ -57,7 +57,7 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -116,7 +116,7 @@ public function testSetNewBillingAddress() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -194,7 +194,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -241,7 +241,7 @@ public function testSetBillingAddressFromAddressBook() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @@ -276,7 +276,7 @@ public function testSetNotExistedBillingAddressFromAddressBook() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -325,7 +325,7 @@ public function testSetNewBillingAddressAndFromAddressBookAtSameTime() * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/Customer/_files/customer_address.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -459,7 +459,7 @@ public function testSetBillingAddressOnNonExistentCart() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php index bd147cc4a197e..b7b7823263106 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php @@ -48,7 +48,7 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php index 98eded8300665..73feefe2b094b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php @@ -41,7 +41,7 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -62,7 +62,7 @@ public function testSetPaymentOnCartWithSimpleProduct() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @@ -100,7 +100,7 @@ public function testSetPaymentOnCartWithVirtualProduct() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -135,7 +135,7 @@ public function testSetPaymentOnNonExistentCart() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -155,7 +155,7 @@ public function testSetPaymentMethodToGuestCart() /** * _security * @magentoApiDataFixture Magento/Customer/_files/three_customers.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -174,7 +174,7 @@ public function testSetPaymentMethodToAnotherCustomerCart() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @@ -227,7 +227,7 @@ public function dataProviderSetPaymentMethodWithoutRequiredParameters(): array /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php index 5ff29d20b34d7..eb366a039d8b3 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php @@ -57,7 +57,7 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -166,7 +166,7 @@ public function testSetNewShippingAddressOnCartWithVirtualProduct() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -211,7 +211,7 @@ public function testSetShippingAddressFromAddressBook() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @@ -248,7 +248,7 @@ public function testSetNonExistentShippingAddressFromAddressBook() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -371,7 +371,7 @@ public function testSetShippingAddressToAnotherCustomerCart() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @@ -427,7 +427,7 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php index 29ddbefd8e405..9219b5a67022c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php @@ -48,7 +48,7 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -86,7 +86,7 @@ public function testSetShippingMethodOnCartWithSimpleProduct() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -124,7 +124,7 @@ public function testReSetShippingMethod() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -257,7 +257,7 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -302,7 +302,7 @@ public function testSetMultipleShippingMethods() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -331,7 +331,7 @@ public function testSetShippingMethodToGuestCart() /** * _security * @magentoApiDataFixture Magento/Customer/_files/three_customers.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -360,7 +360,7 @@ public function testSetShippingMethodToAnotherCustomerCart() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailablePaymentMethodsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailablePaymentMethodsTest.php index 8271a76d88f12..af1f72fe71620 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailablePaymentMethodsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailablePaymentMethodsTest.php @@ -31,7 +31,7 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -52,7 +52,7 @@ public function testGetAvailablePaymentMethods() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -69,7 +69,7 @@ public function testGetAvailablePaymentMethodsFromCustomerCart() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php index 38fda50ba5836..a8113657eff6e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php @@ -33,7 +33,7 @@ protected function setUp() /** * Test case: get available shipping methods from current customer quote * - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -69,7 +69,7 @@ public function testGetAvailableShippingMethods() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -87,7 +87,7 @@ public function testGetAvailableShippingMethodsFromCustomerCart() /** * Test case: get available shipping methods when all shipping methods are disabled * - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php index 6b1f540e4d47a..2649016cf196b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php @@ -28,7 +28,7 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/Catalog/_files/product_virtual.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php index c31b48ccc1087..bfdecca782319 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php @@ -31,7 +31,7 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -61,7 +61,7 @@ public function testGetSelectedShippingMethod() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -79,7 +79,7 @@ public function testGetSelectedShippingMethodFromCustomerCart() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php index 0110384b8f605..d592443aed499 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php @@ -31,7 +31,7 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php @@ -69,7 +69,7 @@ public function testGeSpecifiedBillingAddress() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -118,7 +118,7 @@ public function testGetBillingAddressOfNonExistentCart() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php index ae0a1a0e822ac..6965cd03f86f5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php @@ -28,7 +28,7 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -86,7 +86,7 @@ public function testSetNewBillingAddress() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -208,7 +208,7 @@ public function testSetBillingAddressToCustomerCart() /** * _security - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @@ -280,7 +280,7 @@ public function testSetBillingAddressOnNonExistentCart() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php index 8ed9ef84d6fbd..477c93efd31d0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php @@ -40,7 +40,7 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php index c9078fd84f6bc..879d0fd917291 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php @@ -33,7 +33,7 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -53,7 +53,7 @@ public function testSetPaymentOnCartWithSimpleProduct() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @@ -89,7 +89,7 @@ public function testSetPaymentOnCartWithVirtualProduct() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -122,7 +122,7 @@ public function testSetPaymentOnNonExistentCart() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -141,7 +141,7 @@ public function testSetPaymentMethodToCustomerCart() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -194,7 +194,7 @@ public function dataProviderSetPaymentMethodWithoutRequiredParameters(): array } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php index e21d9ed64d491..18523feb261b9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php @@ -28,7 +28,7 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -135,7 +135,7 @@ public function testSetNewShippingAddressOnCartWithVirtualProduct() /** * _security - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @@ -172,7 +172,7 @@ public function testSetShippingAddressFromAddressBook() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @@ -209,7 +209,7 @@ public function testSetShippingAddressToCustomerCart() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @@ -264,7 +264,7 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php index ca26f8fe5aaf0..2eac002253ff0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php @@ -40,7 +40,7 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -79,7 +79,7 @@ public function testSetShippingMethodOnCartWithSimpleProduct() * Shipping address for quote will be created automatically BUT with NULL values (considered that address * is not set) * - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/Catalog/_files/product_virtual.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php @@ -106,7 +106,7 @@ public function testSetShippingMethodOnCartWithSimpleProductAndWithoutAddress() /** * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -143,7 +143,7 @@ public function testReSetShippingMethod() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -275,7 +275,7 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array /** * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -320,7 +320,7 @@ public function testSetMultipleShippingMethods() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -348,7 +348,7 @@ public function testSetShippingMethodToCustomerCart() /** * _security - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/PlaceOrderTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/PlaceOrderTest.php deleted file mode 100644 index 7d4358b79bdc4..0000000000000 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/PlaceOrderTest.php +++ /dev/null @@ -1,224 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\GraphQl\Quote; - -use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Framework\ObjectManagerInterface; -use Magento\Integration\Api\CustomerTokenServiceInterface; -use Magento\Quote\Api\Data\CartItemInterface; -use Magento\Quote\Model\Quote; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\TestFramework\TestCase\GraphQlAbstract; - -/** - * Test for placing an order - */ -class PlaceOrderTest extends GraphQlAbstract -{ - /** - * @var ObjectManagerInterface - */ - private $objectManager; - - /** - * @var CustomerTokenServiceInterface - */ - private $customerTokenService; - - /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var Quote - */ - private $quote; - - /** - * @var QuoteIdToMaskedQuoteIdInterface - */ - private $quoteIdToMaskedId; - - protected function setUp() - { - $this->objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $this->objectManager->create(QuoteResource::class); - $this->quote = $this->objectManager->create(Quote::class); - $this->quoteIdToMaskedId = $this->objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); - $this->customerTokenService = $this->objectManager->get(CustomerTokenServiceInterface::class); - $this->quoteResource->load( - $this->quote, - 'test_order_1', - 'reserved_order_id' - ); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_check_payment.php - */ - public function testPlaceOrder() - { - $reservedOrderId = 'test_order_1'; - - $query = $this->preparePlaceOrderQuery(); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); - - self::assertArrayHasKey('order_id', $response['placeOrder']['order']); - self::assertEquals($reservedOrderId, $response['placeOrder']['order']['order_id']); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_check_payment.php - */ - public function testPlaceOrderOfAnotherCustomerCart() - { - $query = $this->preparePlaceOrderQuery(); - - self::expectExceptionMessageRegExp('/The current user cannot perform operations on cart*/'); - $this->graphQlQuery($query); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_check_payment.php - */ - public function testPlaceOrderWithOutOfStockProduct() - { - $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); - $product = $productRepository->get('simple'); - $extensionAttributes = $product->getExtensionAttributes(); - $stockItem = $extensionAttributes->getStockItem(); - $stockItem->setIsInStock(false); - $productRepository->save($product); - - $query = $this->preparePlaceOrderQuery(); - - self::expectExceptionMessage('Unable to place order: Some of the products are out of stock'); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_check_payment.php - */ - public function testPlaceOrderWithNoItemsInCart() - { - $quoteItems = $this->quote->getAllItems(); - - /** @var CartItemInterface $quoteItem */ - foreach ($quoteItems as $quoteItem) { - $this->quote->removeItem($quoteItem->getItemId()); - } - $this->quoteResource->save($this->quote); - - $query = $this->preparePlaceOrderQuery(); - - self::expectExceptionMessage( - 'Unable to place order: A server error stopped your order from being placed. ' . - 'Please try to place your order again' - ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_check_payment.php - */ - public function testPlaceOrderWithNoShippingMethod() - { - $this->quote->getShippingAddress()->setShippingMethod(''); - $this->quoteResource->save($this->quote); - - $query = $this->preparePlaceOrderQuery(); - - self::expectExceptionMessage( - 'Unable to place order: The shipping method is missing. Select the shipping method and try again' - ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_check_payment.php - */ - public function testPlaceOrderWithNoShippingAddress() - { - $this->quote->removeAddress($this->quote->getShippingAddress()->getId()); - $this->quoteResource->save($this->quote); - - $query = $this->preparePlaceOrderQuery(); - - self::expectExceptionMessage( - 'Unable to place order: Some addresses can\'t be used due to the configurations for specific countries' - ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_check_payment.php - */ - public function testPlaceOrderWithNoPaymentMethod() - { - $this->quote->getPayment()->setMethod(''); - $this->quoteResource->save($this->quote); - - $query = $this->preparePlaceOrderQuery(); - - self::expectExceptionMessage('Unable to place order: Enter a valid payment method and try again'); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_check_payment.php - */ - public function testPlaceOrderWithNoBillingAddress() - { - $this->quote->removeAddress($this->quote->getBillingAddress()->getId()); - $this->quoteResource->save($this->quote); - - $query = $this->preparePlaceOrderQuery(); - - self::expectExceptionMessageRegExp( - '/Unable to place order: Please check the billing address information*/' - ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); - } - - /** - * Prepares GraphQl query for placing an order - * - * @return string - * @throws \Magento\Framework\Exception\NoSuchEntityException - */ - private function preparePlaceOrderQuery(): string - { - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - - return <<<QUERY -mutation { - placeOrder(input: {cart_id: "$maskedQuoteId"}) { - order { - order_id - } - } -} -QUERY; - } - - /** - * @param string $username - * @param string $password - * @return array - * @throws \Magento\Framework\Exception\AuthenticationException - */ - private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array - { - $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); - $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; - return $headerMap; - } -} diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/set_simple_product_out_of_stock.php b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/set_simple_product_out_of_stock.php new file mode 100644 index 0000000000000..f465f482275c1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/set_simple_product_out_of_stock.php @@ -0,0 +1,19 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +$product = $productRepository->get('simple_product'); +$extensionAttributes = $product->getExtensionAttributes(); +$stockItem = $extensionAttributes->getStockItem(); +$stockItem->setIsInStock(false); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/simple_product.php b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/simple_product.php new file mode 100644 index 0000000000000..732c18d4d7340 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/simple_product.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductInterface; +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\Visibility; +use Magento\Framework\Api\DataObjectHelper; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductInterfaceFactory $productFactory */ +$productFactory = $objectManager->get(ProductInterfaceFactory::class); +/** @var DataObjectHelper $dataObjectHelper */ +$dataObjectHelper = Bootstrap::getObjectManager()->get(DataObjectHelper::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +$product = $productFactory->create(); +$productData = [ + ProductInterface::TYPE_ID => Type::TYPE_SIMPLE, + ProductInterface::ATTRIBUTE_SET_ID => 4, + ProductInterface::SKU => 'simple_product', + ProductInterface::NAME => 'Simple Product', + ProductInterface::PRICE => 10, + ProductInterface::VISIBILITY => Visibility::VISIBILITY_BOTH, + ProductInterface::STATUS => Status::STATUS_ENABLED, +]; +$dataObjectHelper->populateWithArray($product, $productData, ProductInterface::class); +/** Out of interface */ +$product + ->setWebsiteIds([1]) + ->setStockData([ + 'qty' => 85.5, + 'is_in_stock' => true, + 'manage_stock' => true, + 'is_qty_decimal' => true + ]); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/simple_product_rollback.php b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/simple_product_rollback.php new file mode 100644 index 0000000000000..9a54f663c9c13 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/simple_product_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\Registry; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); + +$currentArea = $registry->registry('isSecureArea'); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $productRepository->deleteById('simple_product'); +} catch (\Magento\Framework\Exception\NoSuchEntityException $e) { + /** + * Tests which are wrapped with MySQL transaction clear all data by transaction rollback. + */ +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', $currentArea); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/add_simple_product.php b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/add_simple_product.php index d23381e33d436..f62b463d94003 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/add_simple_product.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/add_simple_product.php @@ -20,7 +20,7 @@ /** @var CartRepositoryInterface $cartRepository */ $cartRepository = Bootstrap::getObjectManager()->get(CartRepositoryInterface::class); -$product = $productRepository->get('simple'); +$product = $productRepository->get('simple_product'); $quote = $quoteFactory->create(); $quoteResource->load($quote, 'test_quote', 'reserved_order_id'); From 2299cf9b4797f8ef32be783acbbbeb380edc03d2 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 3 Apr 2019 14:24:39 -0500 Subject: [PATCH 356/603] GraphQL-295: [Place order] Place order mutation --- .../GraphQl/Quote/Customer/PlaceOrderTest.php | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php index 7ec1a71111835..4220f8932caa1 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php @@ -7,8 +7,12 @@ namespace Magento\GraphQl\Quote\Customer; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Registry; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\ResourceModel\Order\CollectionFactory; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -27,6 +31,21 @@ class PlaceOrderTest extends GraphQlAbstract */ private $getMaskedQuoteIdByReservedOrderId; + /** + * @var CollectionFactory + */ + private $orderCollectionFactory; + + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + + /** + * @var Registry + */ + private $registry; + /** * @inheritdoc */ @@ -35,6 +54,9 @@ protected function setUp() $objectManager = Bootstrap::getObjectManager(); $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->orderCollectionFactory = $objectManager->get(CollectionFactory::class); + $this->orderRepository = $objectManager->get(OrderRepositoryInterface::class); + $this->registry = Bootstrap::getObjectManager()->get(Registry::class); } /** @@ -253,4 +275,22 @@ private function getHeaderMap(string $username = 'customer@example.com', string $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; return $headerMap; } + + /** + * @inheritdoc + */ + public function tearDown() + { + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', true); + + $orderCollection = $this->orderCollectionFactory->create(); + foreach ($orderCollection as $order) { + $this->orderRepository->delete($order); + } + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', false); + + parent::tearDown(); + } } From 436c2dd80309e22379c34626f5e3a102201d737a Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Wed, 3 Apr 2019 15:25:53 -0500 Subject: [PATCH 357/603] MAGETWO-99022: Braintree Displaying Incorrect Ship-To Name - Logger added to controller - Recipient name array cell check added --- .../Magento/Braintree/Controller/Paypal/Review.php | 13 ++++++++++++- .../Braintree/Model/Paypal/Helper/QuoteUpdater.php | 10 ++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Braintree/Controller/Paypal/Review.php b/app/code/Magento/Braintree/Controller/Paypal/Review.php index eb2de7c7b6e39..eb11a2e1adf5e 100644 --- a/app/code/Magento/Braintree/Controller/Paypal/Review.php +++ b/app/code/Magento/Braintree/Controller/Paypal/Review.php @@ -14,6 +14,7 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Framework\App\Action\HttpGetActionInterface; +use Magento\Payment\Model\Method\Logger; /** * Class Review @@ -25,6 +26,11 @@ class Review extends AbstractAction implements HttpPostActionInterface, HttpGetA */ private $quoteUpdater; + /** + * @var Logger + */ + private $logger; + /** * @var string */ @@ -37,15 +43,18 @@ class Review extends AbstractAction implements HttpPostActionInterface, HttpGetA * @param Config $config * @param Session $checkoutSession * @param QuoteUpdater $quoteUpdater + * @param Logger $logger */ public function __construct( Context $context, Config $config, Session $checkoutSession, - QuoteUpdater $quoteUpdater + QuoteUpdater $quoteUpdater, + Logger $logger ) { parent::__construct($context, $config, $checkoutSession); $this->quoteUpdater = $quoteUpdater; + $this->logger = $logger; } /** @@ -84,6 +93,8 @@ public function execute() return $resultPage; } catch (\Exception $e) { $this->messageManager->addExceptionMessage($e, $e->getMessage()); + } finally { + $this->logger->debug($requestData); } /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ diff --git a/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php b/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php index 11c51e07f1dd9..ae2b1b1423640 100644 --- a/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php +++ b/app/code/Magento/Braintree/Model/Paypal/Helper/QuoteUpdater.php @@ -197,8 +197,9 @@ private function updateAddressData(Address $address, array $addressData) */ private function getShippingRecipientFirstName(array $details) { - return explode(' ', $details['shippingAddress']['recipientName'], 2)[0] - ?? $details['firstName']; + return isset($details['shippingAddress']['recipientName']) + ? explode(' ', $details['shippingAddress']['recipientName'], 2)[0] + : $details['firstName']; } /** @@ -209,7 +210,8 @@ private function getShippingRecipientFirstName(array $details) */ private function getShippingRecipientLastName(array $details) { - return explode(' ', $details['shippingAddress']['recipientName'], 2)[1] - ?? $details['lastName']; + return isset($details['shippingAddress']['recipientName']) + ? explode(' ', $details['shippingAddress']['recipientName'], 2)[1] + : $details['lastName']; } } From 54355e36395024e79918ec8b2cca86ce05e3bad0 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 3 Apr 2019 17:48:42 -0500 Subject: [PATCH 358/603] GraphQL-481: [Test Coverage] 'RemoveCouponFromCart' functionality --- .../testsuite/Magento/Quote/Api/CouponManagementTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CouponManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CouponManagementTest.php index 1aee493d8e0cb..13ec50139b7fb 100644 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CouponManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CouponManagementTest.php @@ -93,7 +93,7 @@ public function testSetCouponThrowsExceptionIfCouponDoesNotExist() $serviceInfo = [ 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . $cartId . '/coupons/' . $couponCode, + 'resourcePath' => self::RESOURCE_PATH . $cartId . '/coupons/' . urlencode($couponCode), 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, ], 'soap' => [ @@ -129,7 +129,7 @@ public function testSetCouponSuccess() $couponCode = $salesRule->getPrimaryCoupon()->getCode(); $serviceInfo = [ 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . $cartId . '/coupons/' . $couponCode, + 'resourcePath' => self::RESOURCE_PATH . $cartId . '/coupons/' . urlencode($couponCode), 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, ], 'soap' => [ @@ -232,7 +232,7 @@ public function testSetMyCouponThrowsExceptionIfCouponDoesNotExist() $serviceInfo = [ 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . 'mine/coupons/' . $couponCode, + 'resourcePath' => self::RESOURCE_PATH . 'mine/coupons/' . urlencode($couponCode), 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, 'token' => $token, ], @@ -280,7 +280,7 @@ public function testSetMyCouponSuccess() $serviceInfo = [ 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . 'mine/coupons/' . $couponCode, + 'resourcePath' => self::RESOURCE_PATH . 'mine/coupons/' . urlencode($couponCode), 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, 'token' => $token, ], From d0c9cfa68ca9b9d538e1b743ff87215f510fd6ea Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 3 Apr 2019 17:51:38 -0500 Subject: [PATCH 359/603] GraphQL-295: [Place order] Place order mutation --- .../testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php | 2 +- .../testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php index b1a58d818016e..2cac1f8c4fbf0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php @@ -55,7 +55,7 @@ public function testGetCart() self::assertNotEmpty($response['cart']['items'][0]['id']); self::assertEquals(2, $response['cart']['items'][0]['qty']); - self::assertEquals('simple', $response['cart']['items'][0]['product']['sku']); + self::assertEquals('simple_product', $response['cart']['items'][0]['product']['sku']); self::assertNotEmpty($response['cart']['items'][1]['id']); self::assertEquals(2, $response['cart']['items'][1]['qty']); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php index 2649016cf196b..654b0b963af15 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php @@ -47,7 +47,7 @@ public function testGetCart() self::assertNotEmpty($response['cart']['items'][0]['id']); self::assertEquals(2, $response['cart']['items'][0]['qty']); - self::assertEquals('simple', $response['cart']['items'][0]['product']['sku']); + self::assertEquals('simple_product', $response['cart']['items'][0]['product']['sku']); self::assertNotEmpty($response['cart']['items'][1]['id']); self::assertEquals(2, $response['cart']['items'][1]['qty']); From 0ad0e0528e11bd74dc78ebc7b9eca4e077fbad7d Mon Sep 17 00:00:00 2001 From: Ryan Fowler <ryantfowler9127@gmail.com> Date: Wed, 3 Apr 2019 22:02:46 -0700 Subject: [PATCH 360/603] Update PatchApplierTest.php - Corrected Spelling Corrected spelling error for `patchBacwardCompatability`. --- .../Framework/Setup/Test/Unit/Patch/PatchApplierTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/internal/Magento/Framework/Setup/Test/Unit/Patch/PatchApplierTest.php b/lib/internal/Magento/Framework/Setup/Test/Unit/Patch/PatchApplierTest.php index f89bdc9e137dd..cb40845bcc488 100644 --- a/lib/internal/Magento/Framework/Setup/Test/Unit/Patch/PatchApplierTest.php +++ b/lib/internal/Magento/Framework/Setup/Test/Unit/Patch/PatchApplierTest.php @@ -91,7 +91,7 @@ class PatchApplierTest extends \PHPUnit\Framework\TestCase /** * @var PatchBackwardCompatability |\PHPUnit_Framework_MockObject_MockObject */ - private $patchBacwardCompatability; + private $patchBackwardCompatability; protected function setUp() { @@ -109,7 +109,7 @@ protected function setUp() $this->moduleDataSetupMock->expects($this->any())->method('getConnection')->willReturn($this->connectionMock); $objectManager = new ObjectManager($this); - $this->patchBacwardCompatability = $objectManager->getObject( + $this->patchBackwardCompatability = $objectManager->getObject( PatchBackwardCompatability::class, [ 'moduleResource' => $this->moduleResourceMock @@ -128,7 +128,7 @@ protected function setUp() 'objectManager' => $this->objectManagerMock, 'schemaSetup' => $this->schemaSetupMock, 'moduleDataSetup' => $this->moduleDataSetupMock, - 'patchBackwardCompatability' => $this->patchBacwardCompatability + 'patchBackwardCompatability' => $this->patchBackwardCompatability ] ); require_once __DIR__ . '/../_files/data_patch_classes.php'; From 85155b15cb43131a96d7848bfb770cae513c9207 Mon Sep 17 00:00:00 2001 From: Davit_Zakharyan <davit_zakharyan@epam.com> Date: Thu, 4 Apr 2019 10:00:38 +0400 Subject: [PATCH 361/603] MAGETWO-91523: [2.3] Allowed countries restriction for a default website is applied to backend customer grid - Changed some stepKeys to camel case format. --- .../Test/AllowedCountriesRestrictionApplyOnBackendTest.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml index d8d77b6564987..f39394ef312e4 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml @@ -26,16 +26,16 @@ <!--Create new website,store and store view--> <comment userInput="Create new website,store and store view" stepKey="createWebsite"/> <amOnPage url="{{AdminSystemStorePage.url}}" stepKey="goToAdminSystemStorePage"/> - <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="AdminCreateNewWebsite"> + <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="adminCreateNewWebsite"> <argument name="newWebsiteName" value="{{NewWebSiteData.name}}"/> <argument name="websiteCode" value="{{NewWebSiteData.code}}"/> </actionGroup> - <actionGroup ref="AdminCreateNewStoreGroupActionGroup" stepKey="AdminCreateNewStore"> + <actionGroup ref="AdminCreateNewStoreGroupActionGroup" stepKey="adminCreateNewStore"> <argument name="website" value="{{NewWebSiteData.name}}"/> <argument name="storeGroupName" value="{{NewStoreData.name}}"/> <argument name="storeGroupCode" value="{{NewStoreData.code}}"/> </actionGroup> - <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="AdminCreateNewStoreView"> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="adminCreateNewStoreView"> <argument name="StoreGroup" value="NewStoreData"/> </actionGroup> <!--Set account sharing option - Default value is 'Per Website'--> From 7a888a02edf0a04185cccc1949e58a958df294bd Mon Sep 17 00:00:00 2001 From: Davit_Zakharyan <davit_zakharyan@epam.com> Date: Thu, 4 Apr 2019 11:33:24 +0400 Subject: [PATCH 362/603] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Added automated test script. --- .../Test/Mftf/Data/ShippingMethodsData.xml | 17 +++++++ .../shipping_methods_ups_type_config-meta.xml | 21 +++++++++ .../Page/AdminShippingMethodsConfigPage.xml | 14 ++++++ .../AdminShippingMethodsUpsSection.xml | 16 +++++++ .../Mftf/Test/DefaultConfigForUPSTypeTest.xml | 45 +++++++++++++++++++ 5 files changed, 113 insertions(+) create mode 100644 app/code/Magento/Ups/Test/Mftf/Data/ShippingMethodsData.xml create mode 100644 app/code/Magento/Ups/Test/Mftf/Metadata/shipping_methods_ups_type_config-meta.xml create mode 100644 app/code/Magento/Ups/Test/Mftf/Page/AdminShippingMethodsConfigPage.xml create mode 100644 app/code/Magento/Ups/Test/Mftf/Section/AdminShippingMethodsUpsSection.xml create mode 100644 app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml diff --git a/app/code/Magento/Ups/Test/Mftf/Data/ShippingMethodsData.xml b/app/code/Magento/Ups/Test/Mftf/Data/ShippingMethodsData.xml new file mode 100644 index 0000000000000..d4156d4f3358b --- /dev/null +++ b/app/code/Magento/Ups/Test/Mftf/Data/ShippingMethodsData.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="ShippingMethodsUpsTypeSetDefault" type="shipping_methods_ups_type_config"> + <requiredEntity type="ups_type_inherit">ShippingMethodsUpsTypeDefault</requiredEntity> + </entity> + <entity name="ShippingMethodsUpsTypeDefault" type="ups_type_inherit"> + <data key="inherit">true</data> + </entity> +</entities> diff --git a/app/code/Magento/Ups/Test/Mftf/Metadata/shipping_methods_ups_type_config-meta.xml b/app/code/Magento/Ups/Test/Mftf/Metadata/shipping_methods_ups_type_config-meta.xml new file mode 100644 index 0000000000000..d642b7923282e --- /dev/null +++ b/app/code/Magento/Ups/Test/Mftf/Metadata/shipping_methods_ups_type_config-meta.xml @@ -0,0 +1,21 @@ +<?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="ShippingMethodsUpsTypeConfig" dataType="shipping_methods_ups_type_config" type="create" auth="adminFormKey" url="admin/system_config/save/section/carriers/" method="POST"> + <object key="groups" dataType="shipping_methods_ups_type_config"> + <object key="ups" dataType="shipping_methods_ups_type_config"> + <object key="fields" dataType="shipping_methods_ups_type_config"> + <object key="type" dataType="ups_type_inherit"> + <field key="inherit">boolean</field> + </object> + </object> + </object> + </object> + </operation> +</operations> diff --git a/app/code/Magento/Ups/Test/Mftf/Page/AdminShippingMethodsConfigPage.xml b/app/code/Magento/Ups/Test/Mftf/Page/AdminShippingMethodsConfigPage.xml new file mode 100644 index 0000000000000..ebc44aace6dfb --- /dev/null +++ b/app/code/Magento/Ups/Test/Mftf/Page/AdminShippingMethodsConfigPage.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="AdminShippingMethodsConfigPage" url="admin/system_config/edit/section/carriers/" area="admin" module="Magento_Ups"> + <section name="AdminShippingMethodsUpsSection"/> + </page> +</pages> diff --git a/app/code/Magento/Ups/Test/Mftf/Section/AdminShippingMethodsUpsSection.xml b/app/code/Magento/Ups/Test/Mftf/Section/AdminShippingMethodsUpsSection.xml new file mode 100644 index 0000000000000..4107f17dbc18c --- /dev/null +++ b/app/code/Magento/Ups/Test/Mftf/Section/AdminShippingMethodsUpsSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminShippingMethodsUpsSection"> + <element name="carriersUpsTab" type="button" selector="#carriers_ups-head"/> + <element name="carriersUpsType" type="select" selector="#carriers_ups_type"/> + <element name="selectedUpsType" type="text" selector="#carriers_ups_type option[selected]"/> + </section> +</sections> diff --git a/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml b/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml new file mode 100644 index 0000000000000..9a168f0bd6197 --- /dev/null +++ b/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml @@ -0,0 +1,45 @@ +<?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="DefaultConfigForUPSTypeTest"> + <annotations> + <title value="Default Configuration for UPS Type"/> + <description value="Default Configuration for UPS Type"/> + <features value="Ups"/> + <severity value="MAJOR"/> + <testCaseId value="MAGETWO-99012"/> + <useCaseId value="MAGETWO-98947"/> + <group value="ups"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!--Collapse UPS tab and logout--> + <comment userInput="Collapse UPS tab and logout" stepKey="collapseTabAndLogout"/> + <click selector="{{AdminShippingMethodsUpsSection.carriersUpsTab}}" stepKey="collapseTab"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <!-- Set shipping methods UPS type to default --> + <comment userInput="Set shipping methods UPS type to default" stepKey="setToDefaultShippingMethodsUpsType"/> + <createData entity="ShippingMethodsUpsTypeSetDefault" stepKey="setShippingMethodsUpsTypeToDefault"/> + <!-- Navigate to Stores -> Configuration -> Sales -> Shipping Methods Page --> + <comment userInput="Navigate to Stores -> Configuration -> Sales -> Shipping Methods Page" stepKey="goToAdminShippingMethodsPage"/> + <amonPage url="{{AdminShippingMethodsConfigPage.url}}" stepKey="navigateToAdminShippingMethodsPage"/> + <waitForPageLoad stepKey="waitPageToLoad"/> + <!-- Expand 'UPS' tab --> + <comment userInput="Expand UPS tab" stepKey="expandUpsTab"/> + <conditionalClick selector="{{AdminShippingMethodsUpsSection.carriersUpsTab}}" dependentSelector="{{AdminShippingMethodsUpsSection.carriersUpsType}}" visible="false" stepKey="expandTab"/> + <waitForElementVisible selector="{{AdminShippingMethodsUpsSection.carriersUpsType}}" stepKey="waitTabToExpand"/> + <!-- Assert that selected UPS type by default is 'United Parcel Service XML' --> + <comment userInput="Check that selected UPS type by default is 'United Parcel Service XML'" stepKey="assertDefUpsType"/> + <grabTextFrom selector="{{AdminShippingMethodsUpsSection.selectedUpsType}}" stepKey="grabSelectedOptionText"/> + <assertEquals expected='United Parcel Service XML' expectedType="string" actual="($grabSelectedOptionText)" stepKey="assertDefaultUpsType"/> + </test> +</tests> From 7ee12b065765bd814c5c089da7ba9032569f6cf7 Mon Sep 17 00:00:00 2001 From: priti <priti@twojay.in> Date: Thu, 4 Apr 2019 14:18:33 +0530 Subject: [PATCH 363/603] fixes-for-customer-name-twice-desktop --- .../Customer/view/frontend/templates/account/customer.phtml | 1 - .../Magento/luma/Magento_Theme/web/css/source/_module.less | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/view/frontend/templates/account/customer.phtml b/app/code/Magento/Customer/view/frontend/templates/account/customer.phtml index 2bdb6ac044a92..b7b8796142de8 100644 --- a/app/code/Magento/Customer/view/frontend/templates/account/customer.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/account/customer.phtml @@ -16,7 +16,6 @@ data-toggle="dropdown" data-trigger-keypress-button="true" data-bind="scope: 'customer'"> - <span data-bind="text: customer().fullname"></span> <button type="button" class="action switch" tabindex="-1" diff --git a/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less index cadf575b95fc7..1e942a84d9a16 100644 --- a/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less @@ -104,6 +104,10 @@ font-size: @font-size__base; margin: 0 0 0 15px; + &.customer-welcome{ + margin: 0 0 0 5px; + } + > a { .lib-link( @_link-color: @header-panel__text-color, From 1a297e875a29d0d610180426519a59f91db797d5 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 4 Apr 2019 12:56:19 +0300 Subject: [PATCH 364/603] magento/magento2#21788: Static test fix. --- .../Sales/Model/Order/Email/Sender/CreditmemoSender.php | 2 +- .../Magento/Sales/Model/Order/Email/Sender/InvoiceSender.php | 2 +- .../Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php | 2 +- .../Unit/Model/Order/Creditmemo/Sender/EmailSenderTest.php | 1 - .../Unit/Model/Order/Email/Sender/CreditmemoSenderTest.php | 3 +++ .../Test/Unit/Model/Order/Email/Sender/InvoiceSenderTest.php | 3 +++ .../Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php | 3 +++ 7 files changed, 12 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Sales/Model/Order/Email/Sender/CreditmemoSender.php b/app/code/Magento/Sales/Model/Order/Email/Sender/CreditmemoSender.php index be7fa8296a264..126fe4f93f1e0 100644 --- a/app/code/Magento/Sales/Model/Order/Email/Sender/CreditmemoSender.php +++ b/app/code/Magento/Sales/Model/Order/Email/Sender/CreditmemoSender.php @@ -57,10 +57,10 @@ class CreditmemoSender extends Sender * @param CreditmemoIdentity $identityContainer * @param Order\Email\SenderBuilderFactory $senderBuilderFactory * @param \Psr\Log\LoggerInterface $logger + * @param Renderer $addressRenderer * @param PaymentHelper $paymentHelper * @param CreditmemoResource $creditmemoResource * @param \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig - * @param Renderer $addressRenderer * @param ManagerInterface $eventManager */ public function __construct( diff --git a/app/code/Magento/Sales/Model/Order/Email/Sender/InvoiceSender.php b/app/code/Magento/Sales/Model/Order/Email/Sender/InvoiceSender.php index bd67de7322a62..ba3895cfa1524 100644 --- a/app/code/Magento/Sales/Model/Order/Email/Sender/InvoiceSender.php +++ b/app/code/Magento/Sales/Model/Order/Email/Sender/InvoiceSender.php @@ -57,10 +57,10 @@ class InvoiceSender extends Sender * @param InvoiceIdentity $identityContainer * @param Order\Email\SenderBuilderFactory $senderBuilderFactory * @param \Psr\Log\LoggerInterface $logger + * @param Renderer $addressRenderer * @param PaymentHelper $paymentHelper * @param InvoiceResource $invoiceResource * @param \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig - * @param Renderer $addressRenderer * @param ManagerInterface $eventManager */ public function __construct( diff --git a/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php b/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php index 2b10d25b87a04..10e5e37a49394 100644 --- a/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php +++ b/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php @@ -57,10 +57,10 @@ class ShipmentSender extends Sender * @param ShipmentIdentity $identityContainer * @param Order\Email\SenderBuilderFactory $senderBuilderFactory * @param \Psr\Log\LoggerInterface $logger + * @param Renderer $addressRenderer * @param PaymentHelper $paymentHelper * @param ShipmentResource $shipmentResource * @param \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig - * @param Renderer $addressRenderer * @param ManagerInterface $eventManager */ public function __construct( diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Sender/EmailSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Sender/EmailSenderTest.php index 859fbde31f5d8..467476c9bb406 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Sender/EmailSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Sender/EmailSenderTest.php @@ -1,5 +1,4 @@ <?php - /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/CreditmemoSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/CreditmemoSenderTest.php index 02a2bbec72389..1f074d7262f4d 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/CreditmemoSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/CreditmemoSenderTest.php @@ -7,6 +7,9 @@ use Magento\Sales\Model\Order\Email\Sender\CreditmemoSender; +/** + * Test for Magento\Sales\Model\Order\Email\Sender\CreditmemoSender class. + */ class CreditmemoSenderTest extends AbstractSenderTest { /** diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/InvoiceSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/InvoiceSenderTest.php index ba2f1166baf3c..d1aa5af53da4d 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/InvoiceSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/InvoiceSenderTest.php @@ -7,6 +7,9 @@ use Magento\Sales\Model\Order\Email\Sender\InvoiceSender; +/** + * Test for Magento\Sales\Model\Order\Email\Sender\InvoiceSender class. + */ class InvoiceSenderTest extends AbstractSenderTest { /** diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php index 8a71c738e9fbe..2d7b42bccae5a 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php @@ -7,6 +7,9 @@ use Magento\Sales\Model\Order\Email\Sender\ShipmentSender; +/** + * Test for Magento\Sales\Model\Order\Email\Sender\ShipmentSender class. + */ class ShipmentSenderTest extends AbstractSenderTest { /** From 8a15fd8932709af2705cfe56d478528811c08f01 Mon Sep 17 00:00:00 2001 From: Sergii Ivashchenko <serg.ivashchenko@gmail.com> Date: Thu, 4 Apr 2019 12:52:33 +0100 Subject: [PATCH 365/603] magento-engcom/magento2ce#2731: Fixed static tests --- app/code/Magento/Customer/Model/Customer.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/app/code/Magento/Customer/Model/Customer.php b/app/code/Magento/Customer/Model/Customer.php index e970e3695d4a2..1287dbe5df708 100644 --- a/app/code/Magento/Customer/Model/Customer.php +++ b/app/code/Magento/Customer/Model/Customer.php @@ -1054,17 +1054,6 @@ public function resetErrors() return $this; } - /** - * Prepare customer for delete - * - * @return $this - */ - public function beforeDelete() - { - //TODO : Revisit and figure handling permissions in MAGETWO-11084 Implementation: Service Context Provider - return parent::beforeDelete(); - } - /** * Processing object after save data * From 70e7580f7c1f326c6a6773269c74165c48ef9e16 Mon Sep 17 00:00:00 2001 From: Arnoud Beekman <arnoud.beekman@mediact.nl> Date: Thu, 4 Apr 2019 14:46:15 +0200 Subject: [PATCH 366/603] Remove duplicate styling This styling was defined exactly the same twice. --- .../blank/Magento_Catalog/web/css/source/_module.less | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less index d3b314836ae8e..299c138832064 100644 --- a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less @@ -507,17 +507,6 @@ min-height: inherit; } } - - // - // Category page 1 column layout - // --------------------------------------------- - - .catalog-category-view.page-layout-1column { - .column.main { - min-height: inherit; - } - } - } // From 718bb76ae948b3dc7ddd2ec447fcb0aa291df55c Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Tue, 2 Apr 2019 11:51:09 +0300 Subject: [PATCH 367/603] Fix functional and static tests. --- .../Widget/Block/Adminhtml/Widget/Options.php | 5 +++-- .../Magento/Framework/Data/Form/Element/Label.php | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Widget/Block/Adminhtml/Widget/Options.php b/app/code/Magento/Widget/Block/Adminhtml/Widget/Options.php index 43761d4d4ef2d..32bae10c801c8 100644 --- a/app/code/Magento/Widget/Block/Adminhtml/Widget/Options.php +++ b/app/code/Magento/Widget/Block/Adminhtml/Widget/Options.php @@ -91,7 +91,7 @@ public function getMainFieldset() if ($this->_getData('main_fieldset') instanceof \Magento\Framework\Data\Form\Element\Fieldset) { return $this->_getData('main_fieldset'); } - $mainFieldsetHtmlId = 'options_fieldset' . md5($this->getWidgetType()); + $mainFieldsetHtmlId = 'options_fieldset' . hash('sha256', $this->getWidgetType()); $this->setMainFieldsetHtmlId($mainFieldsetHtmlId); $fieldset = $this->getForm()->addFieldset( $mainFieldsetHtmlId, @@ -141,7 +141,6 @@ protected function _addField($parameter) { $form = $this->getForm(); $fieldset = $this->getMainFieldset(); - //$form->getElement('options_fieldset'); // prepare element data with values (either from request of from default values) $fieldName = $parameter->getKey(); @@ -167,10 +166,12 @@ protected function _addField($parameter) if (is_array($data['value'])) { foreach ($data['value'] as &$value) { if (is_string($value)) { + // phpcs:ignore Magento2.Functions.DiscouragedFunction $value = html_entity_decode($value); } } } else { + // phpcs:ignore Magento2.Functions.DiscouragedFunction $data['value'] = html_entity_decode($data['value']); } diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Label.php b/lib/internal/Magento/Framework/Data/Form/Element/Label.php index d9834b8c15ee1..70b7885e7a0d0 100644 --- a/lib/internal/Magento/Framework/Data/Form/Element/Label.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Label.php @@ -4,13 +4,13 @@ * See COPYING.txt for license details. */ -/** - * Data form abstract class - * - * @author Magento Core Team <core@magentocommerce.com> - */ namespace Magento\Framework\Data\Form\Element; +use Magento\Framework\Phrase; + +/** + * Label form element. + */ class Label extends \Magento\Framework\Data\Form\Element\AbstractElement { /** @@ -37,7 +37,7 @@ public function __construct( public function getElementHtml() { $html = $this->getBold() ? '<div class="control-value special">' : '<div class="control-value">'; - if (is_string($this->getValue())) { + if (is_string($this->getValue()) || $this->getValue() instanceof Phrase) { $html .= $this->getEscapedValue(); } From 861fd86129c5dd40b6f85e8a7f0e779c85fe8b5e Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 4 Apr 2019 17:25:25 +0300 Subject: [PATCH 368/603] magento/magento2#19530: Static test fix. --- .../Data/InstallInitialConfigurableAttributes.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Setup/Patch/Data/InstallInitialConfigurableAttributes.php b/app/code/Magento/ConfigurableProduct/Setup/Patch/Data/InstallInitialConfigurableAttributes.php index 6e608b172b6b1..c6b173453f5ec 100644 --- a/app/code/Magento/ConfigurableProduct/Setup/Patch/Data/InstallInitialConfigurableAttributes.php +++ b/app/code/Magento/ConfigurableProduct/Setup/Patch/Data/InstallInitialConfigurableAttributes.php @@ -6,16 +6,16 @@ namespace Magento\ConfigurableProduct\Setup\Patch\Data; +use Magento\ConfigurableProduct\Model\Product\Type\Configurable; use Magento\Eav\Setup\EavSetup; use Magento\Eav\Setup\EavSetupFactory; -use Magento\Framework\App\ResourceConnection; use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Framework\Setup\Patch\DataPatchInterface; use Magento\Framework\Setup\Patch\PatchVersionInterface; -use Magento\ConfigurableProduct\Model\Product\Type\Configurable; /** * Class InstallInitialConfigurableAttributes + * * @package Magento\ConfigurableProduct\Setup\Patch */ class InstallInitialConfigurableAttributes implements DataPatchInterface, PatchVersionInterface @@ -24,6 +24,7 @@ class InstallInitialConfigurableAttributes implements DataPatchInterface, PatchV * @var ModuleDataSetupInterface */ private $moduleDataSetup; + /** * @var EavSetupFactory */ @@ -43,7 +44,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function apply() { @@ -84,7 +85,7 @@ public function apply() } /** - * {@inheritdoc} + * @inheritdoc */ public static function getDependencies() { @@ -92,7 +93,7 @@ public static function getDependencies() } /** - * {@inheritdoc} + * @inheritdoc */ public static function getVersion() { @@ -100,7 +101,7 @@ public static function getVersion() } /** - * {@inheritdoc} + * @inheritdoc */ public function getAliases() { From c11bafd0a6177e5d2eff7eea52e5f60556221979 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Thu, 4 Apr 2019 09:51:42 -0500 Subject: [PATCH 369/603] Minor fixes for magento/magento-functional-tests-migration#687 - update test annotations - provided additional verification of CAPTCHA --- ...ptchaVisibleOnContactUsFormActionGroup.xml | 21 ++++++ ...illContactUsFormWithCaptchaActionGroup.xml | 17 +++++ .../Test/Mftf/Data/CaptchaConfigData.xml | 6 ++ .../StorefrontContactUsFormSection.xml | 16 +++++ .../Test/Mftf/Test/CaptchaOnContactUsTest.xml | 53 --------------- .../Test/StorefrontCaptchaOnContactUsTest.xml | 64 +++++++++++++++++++ .../StorefrontCaptchaOnCustomerLoginTest.xml | 2 +- .../AssertMessageContactUsFormActionGroup.xml | 18 ++++++ ...StorefrontFillContactUsFormActionGroup.xml | 20 ++++++ ...StorefrontOpenContactUsPageActionGroup.xml | 15 +++++ ...orefrontSubmitContactUsFormActionGroup.xml | 15 +++++ .../Contact/Test/Mftf/Data/ContactUsData.xml | 14 ++++ .../Mftf/Page/StorefrontContactUsPage.xml | 1 - .../StorefrontContactUsFormSection.xml | 9 +-- .../StorefrontContactUsMessagesSection.xml | 14 ++++ 15 files changed, 226 insertions(+), 59 deletions(-) create mode 100644 app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnContactUsFormActionGroup.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontFillContactUsFormWithCaptchaActionGroup.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsFormSection.xml delete mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnContactUsTest.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnContactUsTest.xml create mode 100644 app/code/Magento/Contact/Test/Mftf/ActionGroup/AssertMessageContactUsFormActionGroup.xml create mode 100644 app/code/Magento/Contact/Test/Mftf/ActionGroup/StorefrontFillContactUsFormActionGroup.xml create mode 100644 app/code/Magento/Contact/Test/Mftf/ActionGroup/StorefrontOpenContactUsPageActionGroup.xml create mode 100644 app/code/Magento/Contact/Test/Mftf/ActionGroup/StorefrontSubmitContactUsFormActionGroup.xml create mode 100644 app/code/Magento/Contact/Test/Mftf/Data/ContactUsData.xml create mode 100644 app/code/Magento/Contact/Test/Mftf/Section/StorefrontContactUsMessagesSection.xml diff --git a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnContactUsFormActionGroup.xml b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnContactUsFormActionGroup.xml new file mode 100644 index 0000000000000..d800c65cabb60 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnContactUsFormActionGroup.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="AssertCaptchaVisibleOnContactUsFormActionGroup"> + <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaField}}" stepKey="waitToSeeCaptchaField"/> + <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaImg}}" stepKey="waitToSeeCaptchaImage"/> + <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaReload}}" stepKey="waitToSeeCaptchaReloadButton"/> + <reloadPage stepKey="refreshPage"/> + <waitForPageLoad stepKey="waitForPageReloaded" /> + <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaField}}" stepKey="waitToSeeCaptchaFieldAfterPageReload"/> + <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaImg}}" stepKey="waitToSeeCaptchaImageAfterPageReload"/> + <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaReload}}" stepKey="waitToSeeCaptchaReloadButtonAfterPageReload"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontFillContactUsFormWithCaptchaActionGroup.xml b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontFillContactUsFormWithCaptchaActionGroup.xml new file mode 100644 index 0000000000000..3546fa2e57a33 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/StorefrontFillContactUsFormWithCaptchaActionGroup.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="StorefrontFillContactUsFormWithCaptchaActionGroup" extends="StorefrontFillContactUsFormActionGroup"> + <arguments> + <argument name="captcha" type="string" /> + </arguments> + <fillField stepKey="fillCaptchaField" after="fillComment" userInput="{{captcha}}" selector="{{StorefrontContactUsFormSection.captchaField}}" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml b/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml index 12bbb5b55dab0..b3d26cd7d7af2 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml @@ -27,6 +27,12 @@ <data key="label">Create user</data> <data key="value">user_create</data> </entity> + <entity name="StorefrontCaptchaOnContactUsFormConfigData"> + <data key="path">customer/captcha/forms</data> + <data key="scope_id">0</data> + <data key="label">Contact Us</data> + <data key="value">contact_us</data> + </entity> <entity name="StorefrontCaptchaOnCustomerLoginConfigData"> <!-- Magento default value --> <data key="path">customer/captcha/forms</data> diff --git a/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsFormSection.xml b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsFormSection.xml new file mode 100644 index 0000000000000..60cf961ba7e8c --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsFormSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontContactUsFormSection"> + <element name="captchaField" type="input" selector="#contact-form input[name='captcha[contact_us]']" /> + <element name="captchaImg" type="block" selector="#contact-form img.captcha-img"/> + <element name="captchaReload" type="block" selector="#contact-form button.captcha-reload"/> + </section> +</sections> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnContactUsTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnContactUsTest.xml deleted file mode 100644 index cd839b0f78400..0000000000000 --- a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnContactUsTest.xml +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="CaptchaOnContactUsTest"> - <annotations> - <features value="Captcha"/> - <stories value="Test creation for send comment using the contact us form with captcha."/> - <title value="Captcha contact us form test"/> - <description value="Test creation for send comment using the contact us form with captcha."/> - <severity value="MAJOR"/> - <group value="captcha"/> - <group value="mtf_migrated"/> - </annotations> - <before> - <magentoCLI command="config:set customer/captcha/forms contact_us" stepKey="enableUserEditCaptcha"/> - <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> - </before> - <after> - <magentoCLI command="config:set customer/captcha/forms user_login,user_forgotpassword" stepKey="revertCaptchaConfigurations"/> - <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> - </after> - - <!-- Open storefront contact us form --> - <amOnPage url="{{StorefrontContactUsPage.url}}" stepKey="amOnContactUpPage"/> - <waitForPageLoad stepKey="waitForContactUpPageLoad"/> - - <!-- Check Captcha items --> - <waitForElementVisible selector="{{StorefrontContactUsCaptchaSection.captchaField}}" stepKey="seeCaptchaFieldFirst"/> - <waitForElementVisible selector="{{StorefrontContactUsCaptchaSection.captchaImg}}" stepKey="seeCaptchaImageFirst"/> - <waitForElementVisible selector="{{StorefrontContactUsCaptchaSection.captchaReload}}" stepKey="seeCaptchaReloadButtonFirst"/> - - <!-- Submit Contact Us form --> - <fillField selector="{{StorefrontContactUsFormSection.emailField}}" userInput="{{Simple_US_Customer.email}}" stepKey="fillEmail"/> - <fillField selector="{{StorefrontContactUsFormSection.nameField}}" userInput="{{Simple_US_Customer.firstname}}" stepKey="fillName"/> - <fillField selector="{{StorefrontContactUsFormSection.commentField}}" userInput="Lorem ipsum dolor sit amet, ne enim aliquando eam, oblique deserunt no usu." - stepKey="fillComment"/> - <fillField selector="{{StorefrontContactUsCaptchaSection.captchaField}}" userInput="InvalidCaptcha" stepKey="fillCaptcha" /> - <click selector="{{StorefrontContactUsFormSection.submitFormButton}}" stepKey="clickSubmitFormButton"/> - - <!-- Check Captcha items after form reload --> - <see userInput="Incorrect CAPTCHA" selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="verifyMessage"/> - <waitForElementVisible selector="{{StorefrontContactUsCaptchaSection.captchaField}}" stepKey="seeCaptchaFieldSecond"/> - <waitForElementVisible selector="{{StorefrontContactUsCaptchaSection.captchaImg}}" stepKey="seeCaptchaImageSecond"/> - <waitForElementVisible selector="{{StorefrontContactUsCaptchaSection.captchaReload}}" stepKey="seeCaptchaReloadButtonSecond"/> - </test> -</tests> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnContactUsTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnContactUsTest.xml new file mode 100644 index 0000000000000..4a08576f60a9a --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnContactUsTest.xml @@ -0,0 +1,64 @@ +<?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="StorefrontCaptchaOnContactUsTest"> + <annotations> + <features value="Captcha"/> + <stories value="Submit Contact us form + Captcha"/> + <title value="Captcha on contact us form test"/> + <description value="Test creation for send comment using the contact us form with captcha."/> + <testCaseId value="MC-14103" /> + <severity value="AVERAGE"/> + <group value="captcha"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaLength3ConfigData.path}} {{StorefrontCustomerCaptchaLength3ConfigData.value}}" stepKey="setCaptchaLength" /> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaSymbols1ConfigData.path}} {{StorefrontCustomerCaptchaSymbols1ConfigData.value}}" stepKey="setCaptchaSymbols" /> + <magentoCLI command="config:set {{StorefrontCaptchaOnContactUsFormConfigData.path}} {{StorefrontCaptchaOnContactUsFormConfigData.value}}" stepKey="enableUserEditCaptcha"/> + <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> + </before> + <after> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaDefaultLengthConfigData.path}} {{StorefrontCustomerCaptchaDefaultLengthConfigData.value}}" stepKey="setDefaultCaptchaLength" /> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaDefaultSymbolsConfigData.path}} {{StorefrontCustomerCaptchaDefaultSymbolsConfigData.value}}" stepKey="setDefaultCaptchaSymbols" /> + <magentoCLI command="config:set {{StorefrontCaptchaOnCustomerLoginConfigData.path}} {{StorefrontCaptchaOnCustomerLoginConfigData.value}},{{StorefrontCaptchaOnCustomerForgotPasswordConfigData.value}}" stepKey="enableCaptchaOnDefaultForms" /> + <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> + </after> + + <!-- Open storefront contact us form --> + <actionGroup ref="StorefrontOpenContactUsPageActionGroup" stepKey="goToContactUsPage" /> + + <!-- Check Captcha items --> + <actionGroup ref="AssertCaptchaVisibleOnContactUsFormActionGroup" stepKey="seeCaptchaOnContactUsForm" /> + + <!-- Submit Contact Us form --> + <actionGroup ref="StorefrontFillContactUsFormWithCaptchaActionGroup" stepKey="fillContactUsFormWithWrongCaptcha"> + <argument name="customer" value="Simple_US_Customer" /> + <argument name="contactUsData" value="DefaultContactUsData" /> + <argument name="captcha" value="{{WrongCaptcha.value}}" /> + </actionGroup> + <actionGroup ref="StorefrontSubmitContactUsFormActionGroup" stepKey="submitContactUsFormWithWrongCaptcha" /> + + <!-- Check Captcha items after form reload --> + <actionGroup ref="AssertMessageContactUsFormActionGroup" stepKey="verifyErrorMessage"> + <argument name="message" value="Incorrect CAPTCHA" /> + <argument name="messageType" value="error" /> + </actionGroup> + <actionGroup ref="AssertCaptchaVisibleOnContactUsFormActionGroup" stepKey="seeCaptchaOnContactUsFormAfterWrongCaptcha" /> + + <actionGroup ref="StorefrontFillContactUsFormWithCaptchaActionGroup" stepKey="fillContactUsFormWithCorrectCaptcha"> + <argument name="customer" value="Simple_US_Customer" /> + <argument name="contactUsData" value="DefaultContactUsData" /> + <argument name="captcha" value="{{PreconfiguredCaptcha.value}}" /> + </actionGroup> + <actionGroup ref="StorefrontSubmitContactUsFormActionGroup" stepKey="submitContactUsFormWithCorrectCaptcha" /> + <actionGroup ref="AssertMessageContactUsFormActionGroup" stepKey="verifySuccessMessage" /> + </test> +</tests> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnCustomerLoginTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnCustomerLoginTest.xml index ea63037b0551d..413c1b6c7e3a2 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnCustomerLoginTest.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnCustomerLoginTest.xml @@ -55,7 +55,7 @@ </actionGroup> <actionGroup ref="StorefrontClickSignOnCustomerLoginFormActionGroup" stepKey="clickSignInAccountButtonThirdAttempt" /> <actionGroup ref="AssertMessageCustomerLoginActionGroup" stepKey="seeErrorMessageAfterThirdAttempt" /> - <actionGroup ref="AssertCaptchaVisibleOnCustomerLoginFormActionGroup" stepKey="dontSeeCaptchaAfterThirdAttempt" /> + <actionGroup ref="AssertCaptchaVisibleOnCustomerLoginFormActionGroup" stepKey="seeCaptchaAfterThirdAttempt" /> <!-- Submit form with incorrect captcha --> <actionGroup ref="StorefrontFillCustomerLoginFormWithCaptchaActionGroup" stepKey="fillLoginFormCorrectAccountIncorrectCaptcha"> diff --git a/app/code/Magento/Contact/Test/Mftf/ActionGroup/AssertMessageContactUsFormActionGroup.xml b/app/code/Magento/Contact/Test/Mftf/ActionGroup/AssertMessageContactUsFormActionGroup.xml new file mode 100644 index 0000000000000..eec2194825166 --- /dev/null +++ b/app/code/Magento/Contact/Test/Mftf/ActionGroup/AssertMessageContactUsFormActionGroup.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="AssertMessageContactUsFormActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="Thanks for contacting us with your comments and questions. We'll respond to you very soon." /> + <argument name="messageType" type="string" defaultValue="success" /> + </arguments> + <see userInput="{{message}}" selector="{{StorefrontContactUsMessagesSection.messageByType(messageType)}}" stepKey="verifyMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Contact/Test/Mftf/ActionGroup/StorefrontFillContactUsFormActionGroup.xml b/app/code/Magento/Contact/Test/Mftf/ActionGroup/StorefrontFillContactUsFormActionGroup.xml new file mode 100644 index 0000000000000..df4964ea0423d --- /dev/null +++ b/app/code/Magento/Contact/Test/Mftf/ActionGroup/StorefrontFillContactUsFormActionGroup.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="StorefrontFillContactUsFormActionGroup"> + <arguments> + <argument name="customer" type="entity" /> + <argument name="contactUsData" type="entity" /> + </arguments> + <fillField selector="{{StorefrontContactUsFormSection.nameField}}" userInput="{{customer.firstname}}" stepKey="fillName"/> + <fillField selector="{{StorefrontContactUsFormSection.emailField}}" userInput="{{customer.email}}" stepKey="fillEmail"/> + <fillField selector="{{StorefrontContactUsFormSection.commentField}}" userInput="{{contactUsData.comment}}" stepKey="fillComment"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Contact/Test/Mftf/ActionGroup/StorefrontOpenContactUsPageActionGroup.xml b/app/code/Magento/Contact/Test/Mftf/ActionGroup/StorefrontOpenContactUsPageActionGroup.xml new file mode 100644 index 0000000000000..d333d5d998960 --- /dev/null +++ b/app/code/Magento/Contact/Test/Mftf/ActionGroup/StorefrontOpenContactUsPageActionGroup.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="StorefrontOpenContactUsPageActionGroup"> + <amOnPage url="{{StorefrontContactUsPage.url}}" stepKey="amOnContactUpPage"/> + <waitForPageLoad stepKey="waitForContactUpPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Contact/Test/Mftf/ActionGroup/StorefrontSubmitContactUsFormActionGroup.xml b/app/code/Magento/Contact/Test/Mftf/ActionGroup/StorefrontSubmitContactUsFormActionGroup.xml new file mode 100644 index 0000000000000..f3fe34f20c319 --- /dev/null +++ b/app/code/Magento/Contact/Test/Mftf/ActionGroup/StorefrontSubmitContactUsFormActionGroup.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="StorefrontSubmitContactUsFormActionGroup"> + <click selector="{{StorefrontContactUsFormSection.submitFormButton}}" stepKey="clickSubmitFormButton"/> + <waitForPageLoad stepKey="waitForCommentSubmitted" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Contact/Test/Mftf/Data/ContactUsData.xml b/app/code/Magento/Contact/Test/Mftf/Data/ContactUsData.xml new file mode 100644 index 0000000000000..eadf760776c58 --- /dev/null +++ b/app/code/Magento/Contact/Test/Mftf/Data/ContactUsData.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="DefaultContactUsData"> + <data key="comment" unique="suffix">Lorem ipsum dolor sit amet, ne enim aliquando eam, oblique deserunt no usu. Unique: </data> + </entity> +</entities> diff --git a/app/code/Magento/Contact/Test/Mftf/Page/StorefrontContactUsPage.xml b/app/code/Magento/Contact/Test/Mftf/Page/StorefrontContactUsPage.xml index b8d1de812d887..5e793b2338507 100644 --- a/app/code/Magento/Contact/Test/Mftf/Page/StorefrontContactUsPage.xml +++ b/app/code/Magento/Contact/Test/Mftf/Page/StorefrontContactUsPage.xml @@ -10,6 +10,5 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> <page name="StorefrontContactUsPage" url="/contact/" area="storefront" module="Magento_Contact"> <section name="StorefrontContactUsFormSection"/> - <section name="StorefrontContactUsCaptchaSection"/> </page> </pages> diff --git a/app/code/Magento/Contact/Test/Mftf/Section/StorefrontContactUsFormSection.xml b/app/code/Magento/Contact/Test/Mftf/Section/StorefrontContactUsFormSection.xml index a73d1ad1297ef..fdaddf33f5170 100644 --- a/app/code/Magento/Contact/Test/Mftf/Section/StorefrontContactUsFormSection.xml +++ b/app/code/Magento/Contact/Test/Mftf/Section/StorefrontContactUsFormSection.xml @@ -9,9 +9,10 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontContactUsFormSection"> - <element name="nameField" type="input" selector="#name"/> - <element name="emailField" type="input" selector="#email"/> - <element name="commentField" type="textarea" selector="#comment"/> - <element name="submitFormButton" type="button" selector=".action.submit.primary" timeout="30"/> + <element name="nameField" type="input" selector="#contact-form input[name='name']" /> + <element name="emailField" type="input" selector="#contact-form input[name='email']" /> + <element name="phoneField" type="input" selector="#contact-form input[name='telephone']" /> + <element name="commentField" type="textarea" selector="#contact-form textarea[name='comment']" /> + <element name="submitFormButton" type="button" selector="#contact-form button[type='submit']" timeout="30" /> </section> </sections> diff --git a/app/code/Magento/Contact/Test/Mftf/Section/StorefrontContactUsMessagesSection.xml b/app/code/Magento/Contact/Test/Mftf/Section/StorefrontContactUsMessagesSection.xml new file mode 100644 index 0000000000000..0970f1f8f6b20 --- /dev/null +++ b/app/code/Magento/Contact/Test/Mftf/Section/StorefrontContactUsMessagesSection.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="StorefrontContactUsMessagesSection"> + <element name="messageByType" type="block" selector="#maincontent .message-{{messageType}}" parameterized="true" /> + </section> +</sections> From 30a5a863cb7732ab592bd4f4f18354fa31822024 Mon Sep 17 00:00:00 2001 From: Veronika Kurochkina <veronika_kurochkina@epam.com> Date: Thu, 4 Apr 2019 18:06:49 +0300 Subject: [PATCH 370/603] MAGETWO-58764: [GitHub] Minimal Query Length For Catalog Search #6681 --- .../Model/Search/Adapter/Mysql/Query/Builder/Match.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php b/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php index 8f5aa73e9d12c..b8640f67811f7 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php +++ b/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php @@ -44,7 +44,6 @@ public function __construct( array $preprocessors = [] ) { parent::__construct($resolver, $fulltextHelper, $fulltextSearchMode, $preprocessors); - $this->replaceSymbols = str_split(self::SPECIAL_CHARACTERS, 1); $this->searchHelper = $searchHelper; } @@ -53,6 +52,7 @@ public function __construct( */ protected function prepareQuery($queryValue, $conditionType) { + $this->replaceSymbols = str_split(self::SPECIAL_CHARACTERS, 1); $queryValue = str_replace($this->replaceSymbols, ' ', $queryValue); foreach ($this->preprocessors as $preprocessor) { $queryValue = $preprocessor->process($queryValue); From 5f0bf181fcb2d63d7e42c34ea5bac0e74b450c62 Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Thu, 4 Apr 2019 10:48:42 -0500 Subject: [PATCH 371/603] MC-15729: Create new GraphQL script for our benchmark - part 1 --- setup/performance-toolkit/benchmark.jmx | 538 ++++++++++++++++++++++++ 1 file changed, 538 insertions(+) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index c0d57ba0e2cef..2035da9d58265 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -364,6 +364,16 @@ <stringProp name="Argument.value">${__P(graphQLPoolUsers,1)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> + <elementProp name="graphqlAddConfigurableProductToCartPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlAddConfigurableProductToCartPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlAddConfigurableProductToCartPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="graphqlAddSimpleProductToCartPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlAddSimpleProductToCartPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlAddSimpleProductToCartPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> <elementProp name="graphqlGetCategoryListByCategoryIdPercentage" elementType="Argument"> <stringProp name="Argument.name">graphqlGetCategoryListByCategoryIdPercentage</stringProp> <stringProp name="Argument.value">${__P(graphqlGetCategoryListByCategoryIdPercentage,0)}</stringProp> @@ -40572,6 +40582,534 @@ vars.putObject("category", categories[number]); </hashTree> </hashTree> + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Add Simple Product To Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlAddSimpleProductToCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "Add Simple Product To Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("simple_products_list").size()); +product = props.get("simple_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Simple Product To Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_simple_product_to_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1421843282">addSimpleProductsToCart</stringProp> + <stringProp name="-1173443935">"sku":"${product_sku}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Simple Product From Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_simple_product_from_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1452665323">{"data":{"removeItemFromCart":{"cart":{"items":[]}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Add Configurable Product To Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlAddConfigurableProductToCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "Add Configurable Product To Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("configurable_products_list").size()); +product = props.get("configurable_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract Configurable Product option" enabled="true"> + <stringProp name="VAR">product_option</stringProp> + <stringProp name="JSONPATH">$.data.products.items[0].variants[0].product.sku</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/extract_configurable_product_option.jmx</stringProp></com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Configurable Product To Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_configurable_product_to_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1421843282">addConfigurableProductsToCart</stringProp> + <stringProp name="675049292">"sku":"${product_option}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Configurable Product From Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_configurable_product_from_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1452665323">{"data":{"removeItemFromCart":{"cart":{"items":[]}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + </hashTree> From 9b9044330cea0735b6743b3a4d29d846597785b0 Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Thu, 4 Apr 2019 11:02:50 -0500 Subject: [PATCH 372/603] MAGETWO-99022: Braintree Displaying Incorrect Ship-To Name - Logging moved from finally block --- app/code/Magento/Braintree/Controller/Paypal/Review.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Braintree/Controller/Paypal/Review.php b/app/code/Magento/Braintree/Controller/Paypal/Review.php index eb11a2e1adf5e..2923db6fa88c3 100644 --- a/app/code/Magento/Braintree/Controller/Paypal/Review.php +++ b/app/code/Magento/Braintree/Controller/Paypal/Review.php @@ -66,6 +66,7 @@ public function execute() $this->getRequest()->getPostValue('result', '{}'), true ); + $this->logger->debug($requestData); $quote = $this->checkoutSession->getQuote(); try { @@ -93,8 +94,6 @@ public function execute() return $resultPage; } catch (\Exception $e) { $this->messageManager->addExceptionMessage($e, $e->getMessage()); - } finally { - $this->logger->debug($requestData); } /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ From b71ba967a3ba4efb76778da425529ed9ec94a9cc Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 4 Apr 2019 13:20:20 -0500 Subject: [PATCH 373/603] MAGETWO-98853: reporting_system_updates table exceptionally large (4gb) --- .../Model/Module/Collect.php | 4 +-- .../Test/Unit/Model/Module/CollectTest.php | 12 -------- .../Model/Module/CollectTest.php | 29 +++++++++++++++++++ 3 files changed, 30 insertions(+), 15 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php diff --git a/app/code/Magento/NewRelicReporting/Model/Module/Collect.php b/app/code/Magento/NewRelicReporting/Model/Module/Collect.php index 7e381762f5d27..75adb46987fb3 100644 --- a/app/code/Magento/NewRelicReporting/Model/Module/Collect.php +++ b/app/code/Magento/NewRelicReporting/Model/Module/Collect.php @@ -277,9 +277,7 @@ public function getModuleData($refresh = true) $changes = array_diff($module, $changeTest); $changesCleanArray = $this->getCleanChangesArray($changes); - if (count($changesCleanArray) > 0 || - ($this->moduleManager->isOutputEnabled($changeTest['name']) && - $module['setup_version'] != null)) { + if ($changesCleanArray) { $data = [ 'entity_id' => $changeTest['entity_id'], 'name' => $changeTest['name'], diff --git a/app/code/Magento/NewRelicReporting/Test/Unit/Model/Module/CollectTest.php b/app/code/Magento/NewRelicReporting/Test/Unit/Model/Module/CollectTest.php index 8d8e6255ab8d3..4286406d6e9ab 100644 --- a/app/code/Magento/NewRelicReporting/Test/Unit/Model/Module/CollectTest.php +++ b/app/code/Magento/NewRelicReporting/Test/Unit/Model/Module/CollectTest.php @@ -162,10 +162,6 @@ public function testGetModuleDataWithoutRefresh() ->method('getNames') ->willReturn($enabledModulesMockArray); - $this->moduleManagerMock->expects($this->any())->method('isOutputEnabled')->will( - $this->returnValue(false) - ); - $this->assertInternalType( 'array', $this->model->getModuleData() @@ -256,10 +252,6 @@ public function testGetModuleDataRefresh($data) ->method('getNames') ->willReturn($enabledModulesMockArray); - $this->moduleManagerMock->expects($this->any())->method('isOutputEnabled')->will( - $this->returnValue(true) - ); - $this->assertInternalType( 'array', $this->model->getModuleData() @@ -350,10 +342,6 @@ public function testGetModuleDataRefreshOrStatement($data) ->method('getNames') ->willReturn($enabledModulesMockArray); - $this->moduleManagerMock->expects($this->any())->method('isOutputEnabled')->will( - $this->returnValue(true) - ); - $this->assertInternalType( 'array', $this->model->getModuleData() diff --git a/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php b/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php new file mode 100644 index 0000000000000..4243ca7ab626d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php @@ -0,0 +1,29 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\NewRelicReporting\Model\Module; + +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +class CollectTest extends TestCase +{ + /** + * @var Collect + */ + private $collect; + + protected function setUp() + { + $this->collect = Bootstrap::getObjectManager()->create(Collect::class); + } + + public function testReport() + { + $this->collect->getModuleData(); + $moduleData = $this->collect->getModuleData(); + $this->assertEmpty($moduleData['changes']); + } +} From a56559cfa4c4cdb75605d92a08b8ac6aefa0c896 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 4 Apr 2019 13:48:32 -0500 Subject: [PATCH 374/603] MAGETWO-98853: reporting_system_updates table exceptionally large (4gb) --- app/code/Magento/NewRelicReporting/Model/Module/Collect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/NewRelicReporting/Model/Module/Collect.php b/app/code/Magento/NewRelicReporting/Model/Module/Collect.php index 75adb46987fb3..ac7e4df9331c3 100644 --- a/app/code/Magento/NewRelicReporting/Model/Module/Collect.php +++ b/app/code/Magento/NewRelicReporting/Model/Module/Collect.php @@ -277,7 +277,7 @@ public function getModuleData($refresh = true) $changes = array_diff($module, $changeTest); $changesCleanArray = $this->getCleanChangesArray($changes); - if ($changesCleanArray) { + if (!empty($changesCleanArray)) { $data = [ 'entity_id' => $changeTest['entity_id'], 'name' => $changeTest['name'], From c62e6a691c2af0cea283d6802ae0eaf827ed57eb Mon Sep 17 00:00:00 2001 From: Viktor Tymchynskyi <vtymchynskyi@magento.com> Date: Thu, 14 Mar 2019 16:01:08 -0500 Subject: [PATCH 375/603] MAGETWO-98424: Braintree payment method not supported in multi-shipping - Add support of Braintree and Braintree PayPal payment methods on multi-shipping checkout --- .../Model/Multishipping/PlaceOrder.php | 177 ++++++++++++ app/code/Magento/Braintree/composer.json | 3 +- app/code/Magento/Braintree/etc/config.xml | 8 +- .../Magento/Braintree/etc/frontend/di.xml | 8 + app/code/Magento/Braintree/etc/payment.xml | 10 +- .../layout/multishipping_checkout_billing.xml | 20 ++ .../templates/multishipping/form.phtml | 29 ++ .../templates/multishipping/form_paypal.phtml | 29 ++ .../multishipping/hosted-fields.js | 102 +++++++ .../method-renderer/multishipping/paypal.js | 143 ++++++++++ .../template/payment/multishipping/form.html | 106 ++++++++ .../payment/multishipping/paypal.html | 40 +++ .../frontend/templates/checkout/billing.phtml | 69 +++-- .../layout/multishipping_checkout_billing.xml | 19 ++ .../multishipping/checkmo_form.phtml | 28 ++ .../Fixtures/assign_items_per_address.php | 40 +++ .../Braintree/Fixtures/payment_braintree.php | 28 ++ .../Fixtures/payment_braintree_paypal.php | 28 ++ .../quote_with_split_items_braintree.php | 26 ++ ...uote_with_split_items_braintree_paypal.php | 26 ++ .../Braintree/Model/MultishippingTest.php | 254 ++++++++++++++++++ 21 files changed, 1159 insertions(+), 34 deletions(-) create mode 100644 app/code/Magento/Braintree/Model/Multishipping/PlaceOrder.php create mode 100644 app/code/Magento/Braintree/view/frontend/layout/multishipping_checkout_billing.xml create mode 100644 app/code/Magento/Braintree/view/frontend/templates/multishipping/form.phtml create mode 100644 app/code/Magento/Braintree/view/frontend/templates/multishipping/form_paypal.phtml create mode 100644 app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/multishipping/hosted-fields.js create mode 100644 app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/multishipping/paypal.js create mode 100644 app/code/Magento/Braintree/view/frontend/web/template/payment/multishipping/form.html create mode 100644 app/code/Magento/Braintree/view/frontend/web/template/payment/multishipping/paypal.html create mode 100644 app/code/Magento/OfflinePayments/view/frontend/layout/multishipping_checkout_billing.xml create mode 100644 app/code/Magento/OfflinePayments/view/frontend/templates/multishipping/checkmo_form.phtml create mode 100644 dev/tests/integration/testsuite/Magento/Braintree/Fixtures/assign_items_per_address.php create mode 100644 dev/tests/integration/testsuite/Magento/Braintree/Fixtures/payment_braintree.php create mode 100644 dev/tests/integration/testsuite/Magento/Braintree/Fixtures/payment_braintree_paypal.php create mode 100644 dev/tests/integration/testsuite/Magento/Braintree/Fixtures/quote_with_split_items_braintree.php create mode 100644 dev/tests/integration/testsuite/Magento/Braintree/Fixtures/quote_with_split_items_braintree_paypal.php create mode 100644 dev/tests/integration/testsuite/Magento/Braintree/Model/MultishippingTest.php diff --git a/app/code/Magento/Braintree/Model/Multishipping/PlaceOrder.php b/app/code/Magento/Braintree/Model/Multishipping/PlaceOrder.php new file mode 100644 index 0000000000000..a6c1b088400a7 --- /dev/null +++ b/app/code/Magento/Braintree/Model/Multishipping/PlaceOrder.php @@ -0,0 +1,177 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Braintree\Model\Multishipping; + +use Magento\Braintree\Gateway\Command\GetPaymentNonceCommand; +use Magento\Braintree\Model\Ui\ConfigProvider; +use Magento\Braintree\Observer\DataAssignObserver; +use Magento\Braintree\Model\Ui\PayPal\ConfigProvider as PaypalConfigProvider; +use Magento\Multishipping\Model\Checkout\Type\Multishipping\PlaceOrderInterface; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\Data\OrderPaymentExtensionInterface; +use Magento\Sales\Api\Data\OrderPaymentExtensionInterfaceFactory; +use Magento\Sales\Api\Data\OrderPaymentInterface; +use Magento\Sales\Api\OrderManagementInterface; +use Magento\Vault\Api\Data\PaymentTokenInterface; + +/** + * Order payments processing for multishipping checkout flow. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class PlaceOrder implements PlaceOrderInterface +{ + /** + * @var OrderManagementInterface + */ + private $orderManagement; + + /** + * @var OrderPaymentExtensionInterfaceFactory + */ + private $paymentExtensionFactory; + + /** + * @var GetPaymentNonceCommand + */ + private $getPaymentNonceCommand; + + /** + * @param OrderManagementInterface $orderManagement + * @param OrderPaymentExtensionInterfaceFactory $paymentExtensionFactory + * @param GetPaymentNonceCommand $getPaymentNonceCommand + */ + public function __construct( + OrderManagementInterface $orderManagement, + OrderPaymentExtensionInterfaceFactory $paymentExtensionFactory, + GetPaymentNonceCommand $getPaymentNonceCommand + ) { + $this->orderManagement = $orderManagement; + $this->paymentExtensionFactory = $paymentExtensionFactory; + $this->getPaymentNonceCommand = $getPaymentNonceCommand; + } + + /** + * @inheritdoc + */ + public function place(array $orderList): array + { + if (empty($orderList)) { + return []; + } + + $errorList = []; + $firstOrder = $this->orderManagement->place(array_shift($orderList)); + // get payment token from first placed order + $paymentToken = $this->getPaymentToken($firstOrder); + + foreach ($orderList as $order) { + try { + /** @var OrderInterface $order */ + $orderPayment = $order->getPayment(); + $this->setVaultPayment($orderPayment, $paymentToken); + $this->orderManagement->place($order); + } catch (\Exception $e) { + $incrementId = $order->getIncrementId(); + $errorList[$incrementId] = $e; + } + } + + return $errorList; + } + + /** + * Sets vault payment method. + * + * @param OrderPaymentInterface $orderPayment + * @param PaymentTokenInterface $paymentToken + * @return void + */ + private function setVaultPayment(OrderPaymentInterface $orderPayment, PaymentTokenInterface $paymentToken): void + { + $vaultMethod = $this->getVaultPaymentMethod( + $orderPayment->getMethod() + ); + $orderPayment->setMethod($vaultMethod); + + $publicHash = $paymentToken->getPublicHash(); + $customerId = $paymentToken->getCustomerId(); + $result = $this->getPaymentNonceCommand->execute( + ['public_hash' => $publicHash, 'customer_id' => $customerId] + ) + ->get(); + + $orderPayment->setAdditionalInformation( + DataAssignObserver::PAYMENT_METHOD_NONCE, + $result['paymentMethodNonce'] + ); + $orderPayment->setAdditionalInformation( + PaymentTokenInterface::PUBLIC_HASH, + $publicHash + ); + $orderPayment->setAdditionalInformation( + PaymentTokenInterface::CUSTOMER_ID, + $customerId + ); + } + + /** + * Returns vault payment method. + * + * For placing sequence of orders, we need to replace the original method on the vault method. + * + * @param string $method + * @return string + */ + private function getVaultPaymentMethod(string $method): string + { + $vaultPaymentMap = [ + ConfigProvider::CODE => ConfigProvider::CC_VAULT_CODE, + PaypalConfigProvider::PAYPAL_CODE => PaypalConfigProvider::PAYPAL_VAULT_CODE + ]; + + return $vaultPaymentMap[$method] ?? $method; + } + + /** + * Returns payment token. + * + * @param OrderInterface $order + * @return PaymentTokenInterface + * @throws \BadMethodCallException + */ + private function getPaymentToken(OrderInterface $order): PaymentTokenInterface + { + $orderPayment = $order->getPayment(); + $extensionAttributes = $this->getExtensionAttributes($orderPayment); + $paymentToken = $extensionAttributes->getVaultPaymentToken(); + + if ($paymentToken === null) { + throw new \BadMethodCallException('Vault Payment Token should be defined for placed order payment.'); + } + + return $paymentToken; + } + + /** + * Gets payment extension attributes. + * + * @param OrderPaymentInterface $payment + * @return OrderPaymentExtensionInterface + */ + private function getExtensionAttributes(OrderPaymentInterface $payment): OrderPaymentExtensionInterface + { + $extensionAttributes = $payment->getExtensionAttributes(); + if (null === $extensionAttributes) { + $extensionAttributes = $this->paymentExtensionFactory->create(); + $payment->setExtensionAttributes($extensionAttributes); + } + + return $extensionAttributes; + } +} diff --git a/app/code/Magento/Braintree/composer.json b/app/code/Magento/Braintree/composer.json index 5af56a2afd3fe..2f956076f3846 100644 --- a/app/code/Magento/Braintree/composer.json +++ b/app/code/Magento/Braintree/composer.json @@ -21,7 +21,8 @@ "magento/module-quote": "*", "magento/module-sales": "*", "magento/module-ui": "*", - "magento/module-vault": "*" + "magento/module-vault": "*", + "magento/module-multishipping": "*" }, "suggest": { "magento/module-checkout-agreements": "*", diff --git a/app/code/Magento/Braintree/etc/config.xml b/app/code/Magento/Braintree/etc/config.xml index 9de4773af023a..fe4cfab9c0e30 100644 --- a/app/code/Magento/Braintree/etc/config.xml +++ b/app/code/Magento/Braintree/etc/config.xml @@ -42,7 +42,7 @@ <paymentInfoKeys>cc_type,cc_number,avsPostalCodeResponseCode,avsStreetAddressResponseCode,cvvResponseCode,processorAuthorizationCode,processorResponseCode,processorResponseText,liabilityShifted,liabilityShiftPossible,riskDataId,riskDataDecision</paymentInfoKeys> <avs_ems_adapter>Magento\Braintree\Model\AvsEmsCodeMapper</avs_ems_adapter> <cvv_ems_adapter>Magento\Braintree\Model\CvvEmsCodeMapper</cvv_ems_adapter> - <group>braintree</group> + <group>braintree_group</group> </braintree> <braintree_paypal> <model>BraintreePayPalFacade</model> @@ -68,7 +68,7 @@ <privateInfoKeys>processorResponseCode,processorResponseText,paymentId</privateInfoKeys> <paymentInfoKeys>processorResponseCode,processorResponseText,paymentId,payerEmail</paymentInfoKeys> <supported_locales>en_US,en_GB,en_AU,da_DK,fr_FR,fr_CA,de_DE,zh_HK,it_IT,nl_NL,no_NO,pl_PL,es_ES,sv_SE,tr_TR,pt_BR,ja_JP,id_ID,ko_KR,pt_PT,ru_RU,th_TH,zh_CN,zh_TW</supported_locales> - <group>braintree</group> + <group>braintree_group</group> </braintree_paypal> <braintree_cc_vault> <model>BraintreeCreditCardVaultFacade</model> @@ -78,7 +78,7 @@ <tokenFormat>Magento\Braintree\Model\InstantPurchase\CreditCard\TokenFormatter</tokenFormat> <additionalInformation>Magento\Braintree\Model\InstantPurchase\PaymentAdditionalInformationProvider</additionalInformation> </instant_purchase> - <group>braintree</group> + <group>braintree_group</group> </braintree_cc_vault> <braintree_paypal_vault> <model>BraintreePayPalVaultFacade</model> @@ -88,7 +88,7 @@ <tokenFormat>Magento\Braintree\Model\InstantPurchase\PayPal\TokenFormatter</tokenFormat> <additionalInformation>Magento\Braintree\Model\InstantPurchase\PaymentAdditionalInformationProvider</additionalInformation> </instant_purchase> - <group>braintree</group> + <group>braintree_group</group> </braintree_paypal_vault> </payment> </default> diff --git a/app/code/Magento/Braintree/etc/frontend/di.xml b/app/code/Magento/Braintree/etc/frontend/di.xml index ea417c407dffd..d8d3a93b71dc3 100644 --- a/app/code/Magento/Braintree/etc/frontend/di.xml +++ b/app/code/Magento/Braintree/etc/frontend/di.xml @@ -61,4 +61,12 @@ <argument name="resolver" xsi:type="object">Magento\Braintree\Model\LocaleResolver</argument> </arguments> </type> + <type name="Magento\Multishipping\Model\Checkout\Type\Multishipping\PlaceOrderPool"> + <arguments> + <argument name="services" xsi:type="array"> + <item name="braintree" xsi:type="string">Magento\Braintree\Model\Multishipping\PlaceOrder</item> + <item name="braintree_paypal" xsi:type="string">Magento\Braintree\Model\Multishipping\PlaceOrder</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Braintree/etc/payment.xml b/app/code/Magento/Braintree/etc/payment.xml index dbabd91151022..4cae049aaf5a9 100644 --- a/app/code/Magento/Braintree/etc/payment.xml +++ b/app/code/Magento/Braintree/etc/payment.xml @@ -8,8 +8,16 @@ <payment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Payment:etc/payment.xsd"> <groups> - <group id="braintree"> + <group id="braintree_group"> <label>Braintree</label> </group> </groups> + <methods> + <method name="braintree"> + <allow_multiple_address>1</allow_multiple_address> + </method> + <method name="braintree_paypal"> + <allow_multiple_address>1</allow_multiple_address> + </method> + </methods> </payment> diff --git a/app/code/Magento/Braintree/view/frontend/layout/multishipping_checkout_billing.xml b/app/code/Magento/Braintree/view/frontend/layout/multishipping_checkout_billing.xml new file mode 100644 index 0000000000000..06390d403e63d --- /dev/null +++ b/app/code/Magento/Braintree/view/frontend/layout/multishipping_checkout_billing.xml @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> + <body> + <referenceBlock name="checkout_billing"> + <arguments> + <argument name="form_templates" xsi:type="array"> + <item name="braintree" xsi:type="string">Magento_Braintree::multishipping/form.phtml</item> + <item name="braintree_paypal" xsi:type="string">Magento_Braintree::multishipping/form_paypal.phtml</item> + </argument> + </arguments> + </referenceBlock> + </body> +</page> diff --git a/app/code/Magento/Braintree/view/frontend/templates/multishipping/form.phtml b/app/code/Magento/Braintree/view/frontend/templates/multishipping/form.phtml new file mode 100644 index 0000000000000..bf8aa8dd09c2c --- /dev/null +++ b/app/code/Magento/Braintree/view/frontend/templates/multishipping/form.phtml @@ -0,0 +1,29 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +?> +<script> + require([ + 'uiLayout', + 'jquery' + ], function (layout, $) { + $(function () { + var paymentMethodData = { + method: 'braintree' + }; + layout([ + { + component: 'Magento_Braintree/js/view/payment/method-renderer/multishipping/hosted-fields', + name: 'payment_method_braintree', + method: paymentMethodData.method, + item: paymentMethodData + } + ]); + + $('body').trigger('contentUpdated'); + }) + }) +</script> +<!-- ko template: getTemplate() --><!-- /ko --> diff --git a/app/code/Magento/Braintree/view/frontend/templates/multishipping/form_paypal.phtml b/app/code/Magento/Braintree/view/frontend/templates/multishipping/form_paypal.phtml new file mode 100644 index 0000000000000..ea3eb2214c2d8 --- /dev/null +++ b/app/code/Magento/Braintree/view/frontend/templates/multishipping/form_paypal.phtml @@ -0,0 +1,29 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +?> +<script> + require([ + 'uiLayout', + 'jquery' + ], function (layout, $) { + $(function () { + var paymentMethodData = { + method: 'braintree_paypal' + }; + layout([ + { + component: 'Magento_Braintree/js/view/payment/method-renderer/multishipping/paypal', + name: 'payment_method_braintree_paypal', + method: paymentMethodData.method, + item: paymentMethodData + } + ]); + + $('body').trigger('contentUpdated'); + }) + }) +</script> +<!-- ko template: getTemplate() --><!-- /ko --> diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/multishipping/hosted-fields.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/multishipping/hosted-fields.js new file mode 100644 index 0000000000000..1ceebc8e66282 --- /dev/null +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/multishipping/hosted-fields.js @@ -0,0 +1,102 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ + +define([ + 'jquery', + 'Magento_Braintree/js/view/payment/method-renderer/hosted-fields', + 'Magento_Braintree/js/validator', + 'Magento_Ui/js/model/messageList', + 'mage/translate', + 'Magento_Checkout/js/model/full-screen-loader', + 'Magento_Checkout/js/action/set-payment-information', + 'Magento_Checkout/js/model/payment/additional-validators' +], function ( + $, + Component, + validator, + messageList, + $t, + fullScreenLoader, + setPaymentInformationAction, + additionalValidators +) { + 'use strict'; + + return Component.extend({ + defaults: { + template: 'Magento_Braintree/payment/multishipping/form' + }, + + /** + * Get list of available CC types + * + * @returns {Object} + */ + getCcAvailableTypes: function () { + var availableTypes = validator.getAvailableCardTypes(), + billingCountryId; + + billingCountryId = $('#multishipping_billing_country_id').val(); + + if (billingCountryId && validator.getCountrySpecificCardTypes(billingCountryId)) { + return validator.collectTypes( + availableTypes, validator.getCountrySpecificCardTypes(billingCountryId) + ); + } + + return availableTypes; + }, + + /** + * @override + */ + placeOrder: function () { + var self = this; + + this.validatorManager.validate(self, function () { + return self.setPaymentInformation(); + }); + }, + + /** + * @override + */ + setPaymentInformation: function () { + if (additionalValidators.validate()) { + + fullScreenLoader.startLoader(); + + $.when( + setPaymentInformationAction( + this.messageContainer, + this.getData() + ) + ).done(this.done.bind(this)) + .fail(this.fail.bind(this)); + } + }, + + /** + * {Function} + */ + fail: function () { + fullScreenLoader.stopLoader(); + + return this; + }, + + /** + * {Function} + */ + done: function () { + fullScreenLoader.stopLoader(); + $('#multishipping-billing-form').submit(); + + return this; + } + }); +}); diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/multishipping/paypal.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/multishipping/paypal.js new file mode 100644 index 0000000000000..6702e58d1214b --- /dev/null +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/multishipping/paypal.js @@ -0,0 +1,143 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define([ + 'jquery', + 'underscore', + 'Magento_Braintree/js/view/payment/method-renderer/paypal', + 'Magento_Checkout/js/action/set-payment-information', + 'Magento_Checkout/js/model/payment/additional-validators', + 'Magento_Checkout/js/model/full-screen-loader', + 'mage/translate' +], function ( + $, + _, + Component, + setPaymentInformationAction, + additionalValidators, + fullScreenLoader, + $t +) { + 'use strict'; + + return Component.extend({ + defaults: { + template: 'Magento_Braintree/payment/multishipping/paypal', + submitButtonSelector: '#payment-continue span' + }, + + /** + * @override + */ + onActiveChange: function (isActive) { + this.updateSubmitButtonTitle(isActive); + + this._super(isActive); + }, + + /** + * @override + */ + beforePlaceOrder: function (data) { + this._super(data); + + this.updateSubmitButtonTitle(true); + }, + + /** + * @override + */ + getShippingAddress: function () { + return {}; + }, + + /** + * @override + */ + getData: function () { + var data = this._super(); + + data['additional_data']['is_active_payment_token_enabler'] = true; + + return data; + }, + + /** + * @override + */ + isActiveVault: function () { + return true; + }, + + /** + * Skipping order review step on checkout with multiple addresses is not allowed. + * + * @returns {Boolean} + */ + isSkipOrderReview: function () { + return false; + }, + + /** + * Checks if payment method nonce is already received. + * + * @returns {Boolean} + */ + isPaymentMethodNonceReceived: function () { + return this.paymentMethodNonce !== null; + }, + + /** + * Updates submit button title on multi-addresses checkout billing form. + * + * @param {Boolean} isActive + */ + updateSubmitButtonTitle: function (isActive) { + var title = this.isPaymentMethodNonceReceived() || !isActive ? + $t('Go to Review Your Order') : $t('Continue to PayPal'); + + $(this.submitButtonSelector).html(title); + }, + + /** + * @override + */ + placeOrder: function () { + if (!this.isPaymentMethodNonceReceived()) { + this.payWithPayPal(); + } else { + fullScreenLoader.startLoader(); + + $.when( + setPaymentInformationAction( + this.messageContainer, + this.getData() + ) + ).done(this.done.bind(this)) + .fail(this.fail.bind(this)); + } + }, + + /** + * {Function} + */ + fail: function () { + fullScreenLoader.stopLoader(); + + return this; + }, + + /** + * {Function} + */ + done: function () { + fullScreenLoader.stopLoader(); + $('#multishipping-billing-form').submit(); + + return this; + } + }); +}); diff --git a/app/code/Magento/Braintree/view/frontend/web/template/payment/multishipping/form.html b/app/code/Magento/Braintree/view/frontend/web/template/payment/multishipping/form.html new file mode 100644 index 0000000000000..964e15df166d3 --- /dev/null +++ b/app/code/Magento/Braintree/view/frontend/web/template/payment/multishipping/form.html @@ -0,0 +1,106 @@ +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<div data-bind="attr: {class: 'payment-method payment-method-' + getCode()}, css: {'_active': isActive()}"> + <div> + <form id="co-transparent-form-braintree" class="form" data-bind="" method="post" action="#" novalidate="novalidate"> + <fieldset data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + getCode()}"> + <legend class="legend"> + <span><!-- ko i18n: 'Credit Card Information'--><!-- /ko --></span> + </legend> + <br> + <div class="field type"> + <div class="control"> + <ul class="credit-card-types"> + <!-- ko foreach: {data: getCcAvailableTypes(), as: 'item'} --> + <li class="item" data-bind="css: { + _active: $parent.selectedCardType() == item, + _inactive: $parent.selectedCardType() != null && $parent.selectedCardType() != item + } "> + <!--ko if: $parent.getIcons(item) --> + <img data-bind="attr: { + 'src': $parent.getIcons(item).url, + 'width': $parent.getIcons(item).width, + 'height': $parent.getIcons(item).height + }"> + <!--/ko--> + </li> + <!--/ko--> + </ul> + <input type="hidden" + name="payment[cc_type]" + class="input-text" + value="" + data-bind="attr: {id: getCode() + '_cc_type', 'data-container': getCode() + '-cc-type'}, + value: creditCardType + "> + </div> + </div> + <div class="field number required"> + <label data-bind="attr: {for: getCode() + '_cc_number'}" class="label"> + <span><!-- ko i18n: 'Credit Card Number'--><!-- /ko --></span> + </label> + <div class="control"> + <div data-bind="attr: {id: getCode() + '_cc_number'}" class="hosted-control"></div> + <div class="hosted-error"><!-- ko i18n: 'Please, enter valid Credit Card Number'--><!-- /ko --></div> + </div> + </div> + <div class="field number required"> + <label data-bind="attr: {for: getCode() + '_expiration'}" class="label"> + <span><!-- ko i18n: 'Expiration Date'--><!-- /ko --></span> + </label> + <div class="control"> + <div class="hosted-date-wrap"> + <div data-bind="attr: {id: getCode() + '_expirationMonth'}" + class="hosted-control hosted-date"></div> + + <div data-bind="attr: {id: getCode() + '_expirationYear'}" + class="hosted-control hosted-date"></div> + + <div class="hosted-error"><!-- ko i18n: 'Please, enter valid Expiration Date'--><!-- /ko --></div> + </div> + </div> + </div> + <!-- ko if: (hasVerification())--> + <div class="field cvv required" data-bind="attr: {id: getCode() + '_cc_type_cvv_div'}"> + <label data-bind="attr: {for: getCode() + '_cc_cid'}" class="label"> + <span><!-- ko i18n: 'Card Verification Number'--><!-- /ko --></span> + </label> + <div class="control _with-tooltip"> + <div data-bind="attr: {id: getCode() + '_cc_cid'}" class="hosted-control hosted-cid"></div> + <div class="hosted-error"><!-- ko i18n: 'Please, enter valid Card Verification Number'--><!-- /ko --></div> + + <div class="field-tooltip toggle"> + <span class="field-tooltip-action action-cvv" + tabindex="0" + data-toggle="dropdown" + data-bind="attr: {title: $t('What is this?')}, mageInit: {'dropdown':{'activeClass': '_active'}}"> + <span><!-- ko i18n: 'What is this?'--><!-- /ko --></span> + </span> + <div class="field-tooltip-content" + data-target="dropdown" + data-bind="html: getCvvImageHtml()"></div> + </div> + </div> + </div> + <!-- /ko --> + </fieldset> + <input type="submit" id="braintree_submit" style="display:none" /> + </form> + + <div class="actions-toolbar no-display"> + <div class="primary"> + <button data-role="review-save" + type="submit" + data-bind="{click: placeOrderClick}" + class="action primary checkout"> + <span data-bind="i18n: 'Place Order'"></span> + </button> + </div> + </div> + </div> +</div> \ No newline at end of file diff --git a/app/code/Magento/Braintree/view/frontend/web/template/payment/multishipping/paypal.html b/app/code/Magento/Braintree/view/frontend/web/template/payment/multishipping/paypal.html new file mode 100644 index 0000000000000..722989e41f98f --- /dev/null +++ b/app/code/Magento/Braintree/view/frontend/web/template/payment/multishipping/paypal.html @@ -0,0 +1,40 @@ +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="payment-method" data-bind="css: {'_active': isActive()}"> + <div class="payment-method-title field choice"> + <label class="label" data-bind="attr: {'for': getCode()}"> + <!-- PayPal Logo --> + <img data-bind="attr: {src: getPaymentAcceptanceMarkSrc(), alt: $t('Acceptance Mark'), title: $t('Acceptance Mark')}" + class="payment-icon"/> + <!-- PayPal Logo --> + <span text="getTitle()"></span> + </label> + </div> + + <div class="payment-method-content"> + <each args="getRegion('messages')" render=""></each> + <fieldset class="braintree-paypal-fieldset" data-bind='attr: {id: "payment_form_" + getCode()}'> + <div id="paypal-container"></div> + </fieldset> + <div class="actions-toolbar braintree-paypal-actions" data-bind="visible: isReviewRequired()"> + <div class="payment-method-item braintree-paypal-account"> + <span class="payment-method-type">PayPal</span> + <span class="payment-method-description" text="customerEmail()"></span> + </div> + <div class="actions-toolbar no-display"> + <div class="primary"> + <button data-button="paypal-place" data-role="review-save" + type="submit" + data-bind="{click: placeOrder}" + class="action primary checkout"> + <span data-bind="i18n: 'Place Order'"></span> + </button> + </div> + </div> + </div> + </div> +</div> diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/billing.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/billing.phtml index da553b7823da9..4354cfb7c1c3e 100644 --- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/billing.phtml +++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/billing.phtml @@ -55,6 +55,10 @@ <div class="box-content"> <address> <?= /* @noEscape */ $block->getCheckoutData()->getAddressHtml($block->getAddress()); ?> + <input type="hidden" + id="multishipping_billing_country_id" + value="<?= /* @noEscape */ $block->getAddress()->getCountryId(); ?>" + name="multishipping_billing_country_id"/> </address> </div> </div> @@ -80,35 +84,44 @@ $block->setMethodFormTemplate($code, $methodsForms[$code]); } ?> - <dt class="item-title"> - <?php if ($methodsCount > 1) : ?> - <input type="radio" - id="p_method_<?= $block->escapeHtml($code); ?>" - value="<?= $block->escapeHtml($code); ?>" - name="payment[method]" - title="<?= $block->escapeHtml($_method->getTitle()) ?>" - <?php if ($checked) : ?> - checked="checked" + <div data-bind="scope: 'payment_method_<?= $block->escapeHtml($code);?>'"> + <dt class="item-title"> + <?php if ($methodsCount > 1) : ?> + <input type="radio" + id="p_method_<?= $block->escapeHtml($code); ?>" + value="<?= $block->escapeHtml($code); ?>" + name="payment[method]" + title="<?= $block->escapeHtml($_method->getTitle()) ?>" + data-bind=" + value: getCode(), + checked: isChecked, + click: selectPaymentMethod, + visible: isRadioButtonVisible()" + <?php if ($checked) : ?> + checked="checked" + <?php endif; ?> + class="radio"/> + <?php else : ?> + <input type="radio" + id="p_method_<?= $block->escapeHtml($code); ?>" + value="<?= $block->escapeHtml($code); ?>" + name="payment[method]" + data-bind=" + value: getCode(), + afterRender: selectPaymentMethod" + checked="checked" + class="radio solo method" /> <?php endif; ?> - class="radio"/> - <?php else : ?> - <input type="radio" - id="p_method_<?= $block->escapeHtml($code); ?>" - value="<?= $block->escapeHtml($code); ?>" - name="payment[method]" - checked="checked" - class="radio solo method" /> - <?php endif; ?> - <label for="p_method_<?= $block->escapeHtml($code); ?>"> - <?= $block->escapeHtml($_method->getTitle()) ?> - </label> - </dt> - <?php if ($html = $block->getChildHtml('payment.method.' . $code)) : ?> - <dd class="item-content <?= $checked ? '' : 'no-display'; ?>" - data-bind="scope: 'payment_method_<?= $block->escapeHtml($code);?>'"> - <?= /* @noEscape */ $html; ?> - </dd> - <?php endif; ?> + <label for="p_method_<?= $block->escapeHtml($code); ?>"> + <?= $block->escapeHtml($_method->getTitle()) ?> + </label> + </dt> + <?php if ($html = $block->getChildHtml('payment.method.' . $code)) : ?> + <dd class="item-content <?= $checked ? '' : 'no-display'; ?>"> + <?= /* @noEscape */ $html; ?> + </dd> + <?php endif; ?> + </div> <?php endforeach; ?> </dl> <?= $block->getChildHtml('payment_methods_after') ?> diff --git a/app/code/Magento/OfflinePayments/view/frontend/layout/multishipping_checkout_billing.xml b/app/code/Magento/OfflinePayments/view/frontend/layout/multishipping_checkout_billing.xml new file mode 100644 index 0000000000000..32810ecef20da --- /dev/null +++ b/app/code/Magento/OfflinePayments/view/frontend/layout/multishipping_checkout_billing.xml @@ -0,0 +1,19 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> + <body> + <referenceBlock name="checkout_billing"> + <arguments> + <argument name="form_templates" xsi:type="array"> + <item name="checkmo" xsi:type="string">Magento_OfflinePayments::multishipping/checkmo_form.phtml</item> + </argument> + </arguments> + </referenceBlock> + </body> +</page> diff --git a/app/code/Magento/OfflinePayments/view/frontend/templates/multishipping/checkmo_form.phtml b/app/code/Magento/OfflinePayments/view/frontend/templates/multishipping/checkmo_form.phtml new file mode 100644 index 0000000000000..b96918243a7a7 --- /dev/null +++ b/app/code/Magento/OfflinePayments/view/frontend/templates/multishipping/checkmo_form.phtml @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +?> +<script> + require([ + 'uiLayout', + 'jquery' + ], function (layout, $) { + $(function () { + var paymentMethodData = { + method: 'checkmo' + }; + layout([ + { + component: 'Magento_Checkout/js/view/payment/default', + name: 'payment_method_checkmo', + method: paymentMethodData.method, + item: paymentMethodData + } + ]); + + $('body').trigger('contentUpdated'); + }) + }) +</script> diff --git a/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/assign_items_per_address.php b/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/assign_items_per_address.php new file mode 100644 index 0000000000000..91cea7dc96602 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/assign_items_per_address.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Quote\Api\CartRepositoryInterface; + +$store = $storeManager->getStore(); +$quote->setReservedOrderId('multishipping_quote_id_braintree') + ->setStoreId($store->getId()) + ->setCustomerEmail('customer001@test.com'); + +/** @var CartRepositoryInterface $quoteRepository */ +$quoteRepository = $objectManager->get(CartRepositoryInterface::class); +$quote->collectTotals(); +$quoteRepository->save($quote); + +$items = $quote->getAllItems(); +$addressList = $quote->getAllShippingAddresses(); + +foreach ($addressList as $key => $address) { + $item = $items[$key]; + // set correct quantity per shipping address + $item->setQty(1); + $address->setTotalQty(1); + $address->addItem($item); +} + +// assign virtual product to the billing address +$billingAddress = $quote->getBillingAddress(); +$virtualItem = $items[sizeof($items) - 1]; +$billingAddress->setTotalQty(1); +$billingAddress->addItem($virtualItem); + +// need to recollect totals +$quote->setTotalsCollectedFlag(false); +$quote->collectTotals(); +$quoteRepository->save($quote); diff --git a/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/payment_braintree.php b/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/payment_braintree.php new file mode 100644 index 0000000000000..3e1db90f1f2c8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/payment_braintree.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Quote\Model\Quote\Payment; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use Magento\Quote\Api\Data\PaymentInterface; +use Magento\Braintree\Model\Ui\ConfigProvider; + +/** + * @var Magento\Quote\Model\Quote $quote + */ + +if (empty($quote)) { + throw new \Exception('$quote should be defined in the parent fixture'); +} + +/** @var ObjectManager $objectManager */ +$objectManager = Bootstrap::getObjectManager(); + +/** @var PaymentInterface $payment */ +$payment = $objectManager->create(Payment::class); +$payment->setMethod(ConfigProvider::CODE); +$quote->setPayment($payment); diff --git a/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/payment_braintree_paypal.php b/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/payment_braintree_paypal.php new file mode 100644 index 0000000000000..e4bba222078b0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/payment_braintree_paypal.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Quote\Model\Quote\Payment; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use Magento\Quote\Api\Data\PaymentInterface; +use Magento\Braintree\Model\Ui\PayPal\ConfigProvider; + +/** + * @var Magento\Quote\Model\Quote $quote + */ + +if (empty($quote)) { + throw new \Exception('$quote should be defined in the parent fixture'); +} + +/** @var ObjectManager $objectManager */ +$objectManager = Bootstrap::getObjectManager(); + +/** @var PaymentInterface $payment */ +$payment = $objectManager->create(Payment::class); +$payment->setMethod(ConfigProvider::PAYPAL_CODE); +$quote->setPayment($payment); diff --git a/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/quote_with_split_items_braintree.php b/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/quote_with_split_items_braintree.php new file mode 100644 index 0000000000000..1c56e611dd6db --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/quote_with_split_items_braintree.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Quote\Model\Quote; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; + +/** @var ObjectManager $objectManager */ +$objectManager = Bootstrap::getObjectManager(); + +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); + +/** @var Quote $quote */ +$quote = $objectManager->create(Quote::class); + +require __DIR__ . '/../../../Magento/Multishipping/Fixtures/shipping_address_list.php'; +require __DIR__ . '/../../../Magento/Multishipping/Fixtures/billing_address.php'; +require __DIR__ . '/payment_braintree.php'; +require __DIR__ . '/../../../Magento/Multishipping/Fixtures/items.php'; +require __DIR__ . '/assign_items_per_address.php'; diff --git a/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/quote_with_split_items_braintree_paypal.php b/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/quote_with_split_items_braintree_paypal.php new file mode 100644 index 0000000000000..4bd8e926abb76 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Braintree/Fixtures/quote_with_split_items_braintree_paypal.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Quote\Model\Quote; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; + +/** @var ObjectManager $objectManager */ +$objectManager = Bootstrap::getObjectManager(); + +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); + +/** @var Quote $quote */ +$quote = $objectManager->create(Quote::class); + +require __DIR__ . '/../../../Magento/Multishipping/Fixtures/shipping_address_list.php'; +require __DIR__ . '/../../../Magento/Multishipping/Fixtures/billing_address.php'; +require __DIR__ . '/payment_braintree_paypal.php'; +require __DIR__ . '/../../../Magento/Multishipping/Fixtures/items.php'; +require __DIR__ . '/assign_items_per_address.php'; diff --git a/dev/tests/integration/testsuite/Magento/Braintree/Model/MultishippingTest.php b/dev/tests/integration/testsuite/Magento/Braintree/Model/MultishippingTest.php new file mode 100644 index 0000000000000..91bc0388d8551 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Braintree/Model/MultishippingTest.php @@ -0,0 +1,254 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Braintree\Model; + +use Braintree\Result\Successful; +use Braintree\Transaction; +use Magento\Braintree\Gateway\Command\GetPaymentNonceCommand; +use Magento\Braintree\Model\Adapter\BraintreeAdapter; +use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory; +use Magento\Checkout\Model\Session as CheckoutSession; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Multishipping\Model\Checkout\Type\Multishipping; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Model\Quote; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order\Email\Sender\OrderSender; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use \PHPUnit_Framework_MockObject_MockObject as MockObject; +use Magento\Payment\Gateway\Command\ResultInterface as CommandResultInterface; + +/** + * Tests Magento\Multishipping\Model\Checkout\Type\Multishipping with Braintree and BraintreePayPal payments. + * + * @magentoAppArea frontend + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class MultishippingTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var BraintreeAdapter|MockObject + */ + private $adapter; + + /** + * @var Multishipping + */ + private $model; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + + $orderSender = $this->getMockBuilder(OrderSender::class) + ->disableOriginalConstructor() + ->getMock(); + + $adapterFactory = $this->getMockBuilder(BraintreeAdapterFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->adapter = $this->getMockBuilder(BraintreeAdapter::class) + ->disableOriginalConstructor() + ->getMock(); + $adapterFactory->method('create') + ->willReturn($this->adapter); + + $this->objectManager->addSharedInstance($adapterFactory, BraintreeAdapterFactory::class); + $this->objectManager->addSharedInstance($this->getPaymentNonceMock(), GetPaymentNonceCommand::class); + + $this->model = $this->objectManager->create( + Multishipping::class, + ['orderSender' => $orderSender] + ); + } + + /** + * Checks a case when multiple orders are created successfully using Braintree payment method. + * + * @magentoAppIsolation enabled + * @magentoDataFixture Magento/Braintree/Fixtures/quote_with_split_items_braintree.php + * @magentoConfigFixture current_store payment/braintree/active 1 + * @return void + */ + public function testCreateOrdersWithBraintree() + { + $this->adapter->method('sale') + ->willReturn( + $this->getTransactionStub() + ); + $this->createOrders(); + } + + /** + * Checks a case when multiple orders are created successfully using Braintree PayPal payment method. + * + * @magentoAppIsolation enabled + * @magentoDataFixture Magento/Braintree/Fixtures/quote_with_split_items_braintree_paypal.php + * @magentoConfigFixture current_store payment/braintree_paypal/active 1 + * @return void + */ + public function testCreateOrdersWithBraintreePaypal() + { + $this->adapter->method('sale') + ->willReturn( + $this->getTransactionPaypalStub() + ); + $this->createOrders(); + } + + /** + * Creates orders for multishipping checkout flow. + * + * @return void + */ + private function createOrders() + { + $expectedPlacedOrdersNumber = 3; + $quote = $this->getQuote('multishipping_quote_id_braintree'); + + /** @var CheckoutSession $session */ + $session = $this->objectManager->get(CheckoutSession::class); + $session->replaceQuote($quote); + + $this->model->createOrders(); + + $orderList = $this->getOrderList((int)$quote->getId()); + self::assertCount( + $expectedPlacedOrdersNumber, + $orderList, + 'Total successfully placed orders number mismatch' + ); + } + + /** + * Creates stub for Braintree capture Transaction. + * + * @return Successful + */ + private function getTransactionStub(): Successful + { + $transaction = $this->getMockBuilder(Transaction::class) + ->disableOriginalConstructor() + ->getMock(); + $transaction->status = 'submitted_for_settlement'; + $transaction->creditCard = [ + 'last4' => '1111', + 'cardType' => 'Visa', + 'expirationMonth' => '12', + 'expirationYear' => '2021' + ]; + + $creditCardDetails = new \stdClass(); + $creditCardDetails->token = '4fdg'; + $creditCardDetails->expirationMonth = '12'; + $creditCardDetails->expirationYear = '2021'; + $creditCardDetails->cardType = 'Visa'; + $creditCardDetails->last4 = '1111'; + $creditCardDetails->expirationDate = '12/2021'; + $transaction->creditCardDetails = $creditCardDetails; + + $response = new Successful(); + $response->success = true; + $response->transaction = $transaction; + + return $response; + } + + /** + * Creates stub for BraintreePaypal capture Transaction. + * + * @return Successful + */ + private function getTransactionPaypalStub(): Successful + { + $transaction = $this->getMockBuilder(Transaction::class) + ->disableOriginalConstructor() + ->getMock(); + $transaction->status = 'submitted_for_settlement'; + $transaction->paypal = [ + 'token' => 'fchxqx', + 'payerEmail' => 'payer@example.com', + 'paymentId' => 'PAY-33ac47a28e7f54791f6cda45', + ]; + $paypalDetails = new \stdClass(); + $paypalDetails->token = 'fchxqx'; + $paypalDetails->payerEmail = 'payer@example.com'; + $paypalDetails->paymentId = '33ac47a28e7f54791f6cda45'; + $transaction->paypalDetails = $paypalDetails; + + $response = new Successful(); + $response->success = true; + $response->transaction = $transaction; + + return $response; + } + + /** + * Retrieves quote by reserved order id. + * + * @param string $reservedOrderId + * @return Quote + */ + private function getQuote(string $reservedOrderId): Quote + { + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchCriteriaBuilder->addFilter('reserved_order_id', $reservedOrderId) + ->create(); + + /** @var CartRepositoryInterface $quoteRepository */ + $quoteRepository = $this->objectManager->get(CartRepositoryInterface::class); + $items = $quoteRepository->getList($searchCriteria)->getItems(); + + return array_pop($items); + } + + /** + * Get list of orders by quote id. + * + * @param int $quoteId + * @return array + */ + private function getOrderList(int $quoteId): array + { + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchCriteriaBuilder->addFilter('quote_id', $quoteId) + ->create(); + + /** @var OrderRepositoryInterface $orderRepository */ + $orderRepository = $this->objectManager->get(OrderRepositoryInterface::class); + return $orderRepository->getList($searchCriteria)->getItems(); + } + + /** + * Returns GetPaymentNonceCommand command mock. + * + * @return MockObject + */ + private function getPaymentNonceMock(): MockObject + { + $commandResult = $this->createMock(CommandResultInterface::class); + $commandResult->method('get') + ->willReturn(['paymentMethodNonce' => 'testNonce']); + $paymentNonce = $this->createMock(GetPaymentNonceCommand::class); + $paymentNonce->method('execute') + ->willReturn($commandResult); + + return $paymentNonce; + } +} From 6af0e0068cacd1d66a9f470c4cca5ae7454d0db4 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Thu, 4 Apr 2019 17:10:09 -0500 Subject: [PATCH 376/603] Minor fixes for magento/magento-functional-tests-migration#688 - update test annotations - provided additional verification of CAPTCHA --- .../AssertAdminSuccessLoginActionGroup.xml | 14 ++++ .../AssertMessageOnAdminLoginActionGroup.xml | 18 +++++ .../ActionGroup/LoginAsAdminActionGroup.xml | 6 +- .../Test/Mftf/Section/AdminHeaderSection.xml | 1 + .../Mftf/Section/AdminLoginFormSection.xml | 4 -- .../Section/AdminLoginMessagesSection.xml | 14 ++++ .../AdminLoginWithCaptchaActionGroup.xml | 17 +++++ ...tchaVisibleOnAdminLoginFormActionGroup.xml | 21 ++++++ .../Test/Mftf/Data/CaptchaConfigData.xml | 43 ++++++++++++ .../Mftf/Section/AdminLoginFormSection.xml | 16 +++++ .../Mftf/Test/AdminLoginWithCaptchaTest.xml | 66 ++++++++++++++++++ .../Mftf/Test/CaptchaOnAdminLoginTest.xml | 68 ------------------- ...StorefrontCaptchaEditCustomerEmailTest.xml | 2 +- .../Test/StorefrontCaptchaOnContactUsTest.xml | 2 +- .../StorefrontCaptchaOnCustomerLoginTest.xml | 2 +- ...orefrontCaptchaRegisterNewCustomerTest.xml | 2 +- .../Magento/User/Test/Mftf/Data/UserData.xml | 8 +++ 17 files changed, 225 insertions(+), 79 deletions(-) create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminSuccessLoginActionGroup.xml create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminLoginActionGroup.xml create mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminLoginMessagesSection.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/ActionGroup/AdminLoginWithCaptchaActionGroup.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnAdminLoginFormActionGroup.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/Section/AdminLoginFormSection.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/AdminLoginWithCaptchaTest.xml delete mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnAdminLoginTest.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminSuccessLoginActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminSuccessLoginActionGroup.xml new file mode 100644 index 0000000000000..844f58c789a15 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminSuccessLoginActionGroup.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="AssertAdminSuccessLoginActionGroup"> + <waitForElementVisible selector="{{AdminHeaderSection.adminUserAccountText}}" stepKey="waitForAdminAccountTextVisible" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminLoginActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminLoginActionGroup.xml new file mode 100644 index 0000000000000..ccc7cd24350c5 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminLoginActionGroup.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="AssertMessageOnAdminLoginActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." /> + <argument name="messageType" type="string" defaultValue="error" /> + </arguments> + <see userInput="{{message}}" selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" stepKey="verifyMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginAsAdminActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginAsAdminActionGroup.xml index 1070bc409962a..b2fbadcbe38e2 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginAsAdminActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginAsAdminActionGroup.xml @@ -10,11 +10,11 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="LoginAsAdmin"> <arguments> - <argument name="adminUser" defaultValue="_ENV"/> + <argument name="adminUser" type="entity" defaultValue="DefaultAdminUser"/> </arguments> <amOnPage url="{{AdminLoginPage.url}}" stepKey="navigateToAdmin"/> - <fillField selector="{{AdminLoginFormSection.username}}" userInput="{{adminUser.MAGENTO_ADMIN_USERNAME}}" stepKey="fillUsername"/> - <fillField selector="{{AdminLoginFormSection.password}}" userInput="{{adminUser.MAGENTO_ADMIN_PASSWORD}}" stepKey="fillPassword"/> + <fillField selector="{{AdminLoginFormSection.username}}" userInput="{{adminUser.username}}" stepKey="fillUsername"/> + <fillField selector="{{AdminLoginFormSection.password}}" userInput="{{adminUser.password}}" stepKey="fillPassword"/> <click selector="{{AdminLoginFormSection.signIn}}" stepKey="clickLogin"/> <closeAdminNotification stepKey="closeAdminNotification"/> </actionGroup> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminHeaderSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminHeaderSection.xml index 441ce886f117b..5b517c7be8a79 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminHeaderSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminHeaderSection.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminHeaderSection"> <element name="pageTitle" type="text" selector=".page-header h1.page-title"/> + <element name="adminUserAccountText" type="text" selector=".page-header .admin-user-account-text" /> </section> </sections> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml index 8b28e923cc017..3b10fac7bb9dc 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml @@ -12,9 +12,5 @@ <element name="username" type="input" selector="#username"/> <element name="password" type="input" selector="#login"/> <element name="signIn" type="button" selector=".actions .action-primary" timeout="30"/> - <element name="captchaField" type="input" selector="#captcha"/> - <element name="captchaImg" type="block" selector="#backend_login"/> - <element name="captchaReload" type="block" selector="#captcha-reload"/> - <element name="error" type="text" selector=".message.message-error.error"/> </section> </sections> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginMessagesSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginMessagesSection.xml new file mode 100644 index 0000000000000..f6ada50ada357 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginMessagesSection.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="AdminLoginMessagesSection"> + <element name="messageByType" type="block" selector=".login-content .messages .message-{{messageType}}" parameterized="true" /> + </section> +</sections> diff --git a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AdminLoginWithCaptchaActionGroup.xml b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AdminLoginWithCaptchaActionGroup.xml new file mode 100644 index 0000000000000..07329e2659876 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AdminLoginWithCaptchaActionGroup.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="AdminLoginWithCaptchaActionGroup" extends="LoginAsAdmin"> + <arguments> + <argument name="captcha" type="string" /> + </arguments> + <fillField stepKey="fillCaptchaField" after="fillPassword" userInput="{{captcha}}" selector="{{AdminLoginFormSection.captchaField}}" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnAdminLoginFormActionGroup.xml b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnAdminLoginFormActionGroup.xml new file mode 100644 index 0000000000000..aa02588000d2b --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnAdminLoginFormActionGroup.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="AssertCaptchaVisibleOnAdminLoginFormActionGroup"> + <waitForElementVisible selector="{{AdminLoginFormSection.captchaField}}" stepKey="seeCaptchaField"/> + <waitForElementVisible selector="{{AdminLoginFormSection.captchaImg}}" stepKey="seeCaptchaImage"/> + <waitForElementVisible selector="{{AdminLoginFormSection.captchaReload}}" stepKey="seeCaptchaReloadButton"/> + <reloadPage stepKey="refreshPage"/> + <waitForPageLoad stepKey="waitForPageReloaded" /> + <waitForElementVisible selector="{{AdminLoginFormSection.captchaField}}" stepKey="seeCaptchaFieldAfterPageReload"/> + <waitForElementVisible selector="{{AdminLoginFormSection.captchaImg}}" stepKey="seeCaptchaImageAfterPageReload"/> + <waitForElementVisible selector="{{AdminLoginFormSection.captchaReload}}" stepKey="seeCaptchaReloadButtonAfterPageReload"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml b/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml index b3d26cd7d7af2..90f48c320f2ac 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml @@ -96,4 +96,47 @@ <data key="label">ABCDEFGHJKMnpqrstuvwxyz23456789</data> <data key="value">ABCDEFGHJKMnpqrstuvwxyz23456789</data> </entity> + <entity name="AdminCaptchaEnableConfigData"> + <!-- Magento default value --> + <data key="path">admin/captcha/enable</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="AdminCaptchaDisableConfigData"> + <data key="path">admin/captcha/enable</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="AdminCaptchaLength3ConfigData"> + <data key="path">admin/captcha/length</data> + <data key="scope">admin</data> + <data key="scope_id">1</data> + <data key="label">3</data> + <data key="value">3</data> + </entity> + <entity name="AdminCaptchaSymbols1ConfigData"> + <data key="path">admin/captcha/symbols</data> + <data key="scope">admin</data> + <data key="scope_id">1</data> + <data key="label">1</data> + <data key="value">1</data> + </entity> + <entity name="AdminCaptchaDefaultLengthConfigData"> + <!-- Magento default value --> + <data key="path">admin/captcha/length</data> + <data key="scope">admin</data> + <data key="scope_id">1</data> + <data key="label">4-5</data> + <data key="value">4-5</data> + </entity> + <entity name="AdminCaptchaDefaultSymbolsConfigData"> + <!-- Magento default value --> + <data key="path">admin/captcha/symbols</data> + <data key="scope">admin</data> + <data key="scope_id">1</data> + <data key="label">ABCDEFGHJKMnpqrstuvwxyz23456789</data> + <data key="value">ABCDEFGHJKMnpqrstuvwxyz23456789</data> + </entity> </entities> diff --git a/app/code/Magento/Captcha/Test/Mftf/Section/AdminLoginFormSection.xml b/app/code/Magento/Captcha/Test/Mftf/Section/AdminLoginFormSection.xml new file mode 100644 index 0000000000000..2bcc6fc542d82 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Section/AdminLoginFormSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminLoginFormSection"> + <element name="captchaField" type="input" selector="#login-form input[name='captcha[backend_login]']" /> + <element name="captchaImg" type="block" selector="#login-form img#backend_login"/> + <element name="captchaReload" type="block" selector="#login-form img#captcha-reload"/> + </section> +</sections> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/AdminLoginWithCaptchaTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/AdminLoginWithCaptchaTest.xml new file mode 100644 index 0000000000000..6c3bf9b127b1e --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Test/AdminLoginWithCaptchaTest.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="AdminLoginWithCaptchaTest"> + <annotations> + <features value="Captcha"/> + <stories value="Admin login + Captcha"/> + <title value="Captcha on Admin login form"/> + <description value="Test creation for admin login with captcha."/> + <testCaseId value="MC-14012" /> + <severity value="MAJOR"/> + <group value="captcha"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <magentoCLI command="config:set {{AdminCaptchaLength3ConfigData.path}} {{AdminCaptchaLength3ConfigData.value}}" stepKey="setCaptchaLength" /> + <magentoCLI command="config:set {{AdminCaptchaSymbols1ConfigData.path}} {{AdminCaptchaSymbols1ConfigData.value}}" stepKey="setCaptchaSymbols" /> + </before> + <after> + <magentoCLI command="config:set {{AdminCaptchaDefaultLengthConfigData.path}} {{AdminCaptchaDefaultLengthConfigData.value}}" stepKey="setDefaultCaptchaLength" /> + <magentoCLI command="config:set {{AdminCaptchaDefaultSymbolsConfigData.path}} {{AdminCaptchaDefaultSymbolsConfigData.value}}" stepKey="setDefaultCaptchaSymbols" /> + </after> + + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdminWithWrongCredentialsFirstAttempt"> + <argument name="adminUser" value="AdminUserWrongCredentials" /> + </actionGroup> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeFirstLoginErrorMessage" /> + + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdminWithWrongCredentialsSecondAttempt"> + <argument name="adminUser" value="AdminUserWrongCredentials" /> + </actionGroup> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeSecondLoginErrorMessage" /> + + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdminWithWrongCredentialsThirdAttempt"> + <argument name="adminUser" value="AdminUserWrongCredentials" /> + </actionGroup> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeThirdLoginErrorMessage" /> + + <!-- Check captcha visibility on admin login page --> + <actionGroup ref="AssertCaptchaVisibleOnAdminLoginFormActionGroup" stepKey="assertCaptchaVisible" /> + + <!-- Submit form with incorrect captcha --> + <actionGroup ref="AdminLoginWithCaptchaActionGroup" stepKey="loginAsAdminWithIncorrectCaptcha"> + <argument name="adminUser" value="DefaultAdminUser" /> + <argument name="captcha" value="{{WrongCaptcha.value}}" /> + </actionGroup> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeIncorrectCaptchaErrorMessage"> + <argument name="message" value="Incorrect CAPTCHA." /> + </actionGroup> + <actionGroup ref="AssertCaptchaVisibleOnAdminLoginFormActionGroup" stepKey="assertCaptchaVisibleAfterIncorrectCaptcha" /> + + <actionGroup ref="AdminLoginWithCaptchaActionGroup" stepKey="loginAsAdminWithCorrectCaptcha"> + <argument name="adminUser" value="DefaultAdminUser" /> + <argument name="captcha" value="{{PreconfiguredCaptcha.value}}" /> + </actionGroup> + <actionGroup ref="AssertAdminSuccessLoginActionGroup" stepKey="verifyAdminLoggedIn" /> + </test> +</tests> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnAdminLoginTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnAdminLoginTest.xml deleted file mode 100644 index d830c0723ba89..0000000000000 --- a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnAdminLoginTest.xml +++ /dev/null @@ -1,68 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="CaptchaOnAdminLoginTest"> - <annotations> - <features value="Captcha"/> - <stories value="Test creation for send comment using the contact us form with captcha."/> - <title value="Captcha contact us form test"/> - <description value="Test creation for send comment using the contact us form with captcha."/> - <severity value="MAJOR"/> - <group value="captcha"/> - <group value="mtf_migrated"/> - </annotations> - <before> - - </before> - <after> - - </after> - <!-- Open admin login page --> - <amOnPage url="{{AdminLoginPage.url}}" stepKey="goToAdminLoginPage" /> - <waitForPageLoad stepKey="waitForPageLoad1" /> - - <!-- Login as Admin with incorrect credentials 3 times --> - <actionGroup ref="LoginAdminWithCredentialsActionGroup" stepKey="failedFirstLoginAdminUser"> - <argument name="adminUser" value="adminUser" /> - <argument name="adminPassword" value="INVALIDAdminPassword" /> - </actionGroup> - <see userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." - selector="{{AdminLoginFormSection.error}}" stepKey="seeFirstLoginError"/> - - <actionGroup ref="LoginAdminWithCredentialsActionGroup" stepKey="failedSecondLoginAdminUser"> - <argument name="adminUser" value="adminUser" /> - <argument name="adminPassword" value="INVALIDAdminPassword" /> - </actionGroup> - <see userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." - selector="{{AdminLoginFormSection.error}}" stepKey="seeSecondLoginError"/> - - <actionGroup ref="LoginAdminWithCredentialsActionGroup" stepKey="failedThirdLoginAdminUser"> - <argument name="adminUser" value="adminUser" /> - <argument name="adminPassword" value="INVALIDAdminPassword" /> - </actionGroup> - <see userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." - selector="{{AdminLoginFormSection.error}}" stepKey="seeThirdLoginError"/> - - <!-- Check captcha visibility on admin login page --> - <waitForElementVisible selector="{{AdminLoginFormSection.captchaField}}" stepKey="seeFirstCaptchaField"/> - <waitForElementVisible selector="{{AdminLoginFormSection.captchaImg}}" stepKey="seeFirstCaptchaImage"/> - <waitForElementVisible selector="{{AdminLoginFormSection.captchaReload}}" stepKey="seeFirstCaptchaReloadButton"/> - - <!-- Submit form with incorrect captcha --> - <fillField selector="{{AdminLoginFormSection.username}}" userInput="adminUser" stepKey="fillAdminUserNameWithCaptcha"/> - <fillField selector="{{AdminLoginFormSection.password}}" userInput="adminPassword" stepKey="fillPasswordWithCaptcha"/> - <fillField selector="{{AdminLoginFormSection.captchaField}}" userInput="incorrectCaptcha" stepKey="fillCaptcha"/> - <click selector="{{AdminLoginFormSection.signIn}}" stepKey="clickLoginWithCaptcha"/> - <see userInput="Incorrect CAPTCHA." selector="{{AdminLoginFormSection.error}}" stepKey="seeCaptchaError"/> - <waitForElementVisible selector="{{AdminLoginFormSection.captchaField}}" stepKey="seeSecondCaptchaField"/> - <waitForElementVisible selector="{{AdminLoginFormSection.captchaImg}}" stepKey="seeSecondCaptchaImage"/> - <waitForElementVisible selector="{{AdminLoginFormSection.captchaReload}}" stepKey="seeSecondCaptchaReloadButton"/> - </test> -</tests> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaEditCustomerEmailTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaEditCustomerEmailTest.xml index 99ce58bc3d174..54237087227d8 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaEditCustomerEmailTest.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaEditCustomerEmailTest.xml @@ -15,7 +15,7 @@ <title value="Test for checking captcha on the customer account edit page."/> <description value="Test for checking captcha on the customer account edit page and customer is locked."/> <testCaseId value="MC-14013" /> - <severity value="AVERAGE"/> + <severity value="MAJOR"/> <group value="captcha"/> <group value="mtf_migrated"/> </annotations> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnContactUsTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnContactUsTest.xml index 4a08576f60a9a..0c6a3f31c1df2 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnContactUsTest.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnContactUsTest.xml @@ -15,7 +15,7 @@ <title value="Captcha on contact us form test"/> <description value="Test creation for send comment using the contact us form with captcha."/> <testCaseId value="MC-14103" /> - <severity value="AVERAGE"/> + <severity value="MAJOR"/> <group value="captcha"/> <group value="mtf_migrated"/> </annotations> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnCustomerLoginTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnCustomerLoginTest.xml index 413c1b6c7e3a2..5a1be68d3f251 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnCustomerLoginTest.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaOnCustomerLoginTest.xml @@ -14,7 +14,7 @@ <stories value="Login with Customer Account + Captcha"/> <title value="Captcha customer login page test"/> <description value="Check CAPTCHA on Storefront Login Page."/> - <severity value="AVERAGE"/> + <severity value="MAJOR"/> <testCaseId value="MC-14010" /> <group value="captcha"/> <group value="mtf_migrated"/> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaRegisterNewCustomerTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaRegisterNewCustomerTest.xml index cce8a1570682b..2c331f958e467 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaRegisterNewCustomerTest.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaRegisterNewCustomerTest.xml @@ -14,7 +14,7 @@ <stories value="Create New Customer Account + Captcha"/> <title value="Test creation for customer register with captcha on storefront."/> <description value="Test creation for customer register with captcha on storefront."/> - <severity value="AVERAGE"/> + <severity value="MAJOR"/> <testCaseId value="MC-14805" /> <group value="captcha"/> <group value="mtf_migrated"/> diff --git a/app/code/Magento/User/Test/Mftf/Data/UserData.xml b/app/code/Magento/User/Test/Mftf/Data/UserData.xml index 80c1cc3022964..d602f094ce4e5 100644 --- a/app/code/Magento/User/Test/Mftf/Data/UserData.xml +++ b/app/code/Magento/User/Test/Mftf/Data/UserData.xml @@ -8,6 +8,14 @@ <entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="DefaultAdminUser" type="user"> + <data key="username">{{_ENV.MAGENTO_ADMIN_USERNAME}}</data> + <data key="password">{{_ENV.MAGENTO_ADMIN_PASSWORD}}</data> + </entity> + <entity name="AdminUserWrongCredentials"> + <data key="username" unique="suffix">username_</data> + <data key="password" unique="suffix">password_</data> + </entity> <entity name="admin" type="user"> <data key="email">admin@magento.com</data> <data key="password">admin123</data> From e84784133d050a8b8a96a1704338f131dd16ef6a Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Thu, 4 Apr 2019 17:12:00 -0500 Subject: [PATCH 377/603] 229: [GraphQL caching] Add support for queries via HTTP GET - Address review comments - Add customer validator interface for graphql requests --- .../Magento/GraphQl/Controller/GraphQl.php | 80 +++++--------- .../ContentTypeProcessor.php | 37 ------- .../HttpHeaderProcessor/StoreProcessor.php | 4 +- .../HttpHeaderProcessorInterface.php | 5 +- .../Controller/HttpRequestProcessor.php | 24 ++++- .../ContentTypeValidator.php | 40 +++++++ .../HttpVerbValidator.php | 40 +++++++ .../HttpRequestValidatorInterface.php | 24 +++++ app/code/Magento/GraphQl/etc/graphql/di.xml | 5 +- .../TestFramework/TestCase/GraphQl/Client.php | 46 ++++---- .../TestCase/GraphQlAbstract.php | 54 ++++++---- .../CatalogInventory/AddProductToCartTest.php | 4 +- .../Customer/ChangeCustomerPasswordTest.php | 8 +- .../Customer/CreateCustomerAddressTest.php | 6 +- .../GraphQl/Customer/CreateCustomerTest.php | 12 +-- .../Customer/DeleteCustomerAddressTest.php | 10 +- .../Customer/GenerateCustomerTokenTest.php | 4 +- .../Customer/RevokeCustomerTokenTest.php | 4 +- .../Customer/SubscriptionStatusTest.php | 9 +- .../Customer/UpdateCustomerAddressTest.php | 6 +- .../GraphQl/Customer/UpdateCustomerTest.php | 14 +-- .../AddConfigurableProductToCartTest.php | 6 +- .../Quote/AddSimpleProductToCartTest.php | 6 +- .../Magento/GraphQl/Quote/CouponTest.php | 16 +-- .../Quote/Customer/CreateEmptyCartTest.php | 2 +- .../Quote/Customer/RemoveItemFromCartTest.php | 14 +-- .../Customer/SetBillingAddressOnCartTest.php | 20 ++-- .../SetOfflineShippingMethodsOnCartTest.php | 2 +- .../Customer/SetPaymentMethodOnCartTest.php | 18 ++-- .../Customer/SetShippingAddressOnCartTest.php | 18 ++-- .../Customer/SetShippingMethodsOnCartTest.php | 14 +-- .../Quote/Customer/UpdateCartItemsTest.php | 18 ++-- .../Quote/Guest/CreateEmptyCartTest.php | 2 +- .../Quote/Guest/RemoveItemFromCartTest.php | 12 +-- .../Guest/SetBillingAddressOnCartTest.php | 12 +-- .../SetOfflineShippingMethodsOnCartTest.php | 2 +- .../Guest/SetPaymentMethodOnCartTest.php | 16 +-- .../Guest/SetShippingAddressOnCartTest.php | 12 +-- .../Guest/SetShippingMethodsOnCartTest.php | 14 +-- .../Quote/Guest/UpdateCartItemsTest.php | 16 +-- .../GraphQl/SendFriend/SendFriendTest.php | 10 +- .../TestModule/GraphQlMutationTest.php | 2 +- .../GraphQl/TestModule/GraphQlQueryTest.php | 22 ++++ .../Ups/SetUpsShippingMethodsOnCartTest.php | 2 +- .../Vault/CustomerPaymentTokensTest.php | 6 +- .../Controller/GraphQlControllerTest.php | 102 +++++++++--------- .../Exception/GraphQlRequestException.php | 54 ---------- 47 files changed, 450 insertions(+), 404 deletions(-) delete mode 100644 app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/ContentTypeProcessor.php create mode 100644 app/code/Magento/GraphQl/Controller/HttpRequestValidator/ContentTypeValidator.php create mode 100644 app/code/Magento/GraphQl/Controller/HttpRequestValidator/HttpVerbValidator.php create mode 100644 app/code/Magento/GraphQl/Controller/HttpRequestValidatorInterface.php delete mode 100644 lib/internal/Magento/Framework/GraphQl/Exception/GraphQlRequestException.php diff --git a/app/code/Magento/GraphQl/Controller/GraphQl.php b/app/code/Magento/GraphQl/Controller/GraphQl.php index 6c37a5709a0bd..9e27ca5d608f0 100644 --- a/app/code/Magento/GraphQl/Controller/GraphQl.php +++ b/app/code/Magento/GraphQl/Controller/GraphQl.php @@ -12,7 +12,7 @@ use Magento\Framework\App\RequestInterface; use Magento\Framework\App\ResponseInterface; use Magento\Framework\GraphQl\Exception\ExceptionFormatter; -use Magento\Framework\GraphQl\Exception\GraphQlRequestException; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\QueryProcessor; use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; use Magento\Framework\GraphQl\Schema\SchemaGeneratorInterface; @@ -24,7 +24,6 @@ * Front controller for web API GraphQL area. * * @api - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class GraphQl implements FrontControllerInterface { @@ -49,12 +48,12 @@ class GraphQl implements FrontControllerInterface private $queryProcessor; /** - * @var \Magento\Framework\GraphQl\Exception\ExceptionFormatter + * @var ExceptionFormatter */ private $graphQlError; /** - * @var \Magento\Framework\GraphQl\Query\Resolver\ContextInterface + * @var ContextInterface */ private $resolverContext; @@ -73,8 +72,8 @@ class GraphQl implements FrontControllerInterface * @param SchemaGeneratorInterface $schemaGenerator * @param SerializerInterface $jsonSerializer * @param QueryProcessor $queryProcessor - * @param \Magento\Framework\GraphQl\Exception\ExceptionFormatter $graphQlError - * @param \Magento\Framework\GraphQl\Query\Resolver\ContextInterface $resolverContext + * @param ExceptionFormatter $graphQlError + * @param ContextInterface $resolverContext * @param HttpRequestProcessor $requestProcessor * @param QueryFields $queryFields */ @@ -109,30 +108,24 @@ public function dispatch(RequestInterface $request) : ResponseInterface $statusCode = 200; try { /** @var Http $request */ - if ($this->isHttpVerbValid($request)) { - $this->requestProcessor->processHeaders($request); - $data = $this->getDataFromRequest($request); - $query = isset($data['query']) ? $data['query'] : ''; - $variables = isset($data['variables']) ? $data['variables'] : null; - - // We must extract queried field names to avoid instantiation of unnecessary fields in webonyx schema - // Temporal coupling is required for performance optimization - $this->queryFields->setQuery($query, $variables); - $schema = $this->schemaGenerator->generate(); - - $result = $this->queryProcessor->process( - $schema, - $query, - $this->resolverContext, - isset($data['variables']) ? $data['variables'] : [] - ); - } else { - $errorMessage = __('Mutation requests allowed only for POST requests'); - $result['errors'] = [ - $this->graphQlError->create(new GraphQlRequestException($errorMessage)) - ]; - $statusCode = ExceptionFormatter::HTTP_GRAPH_QL_SCHEMA_ERROR_STATUS; - } + $this->requestProcessor->validateRequest($request); + $this->requestProcessor->processHeaders($request); + + $data = $this->getDataFromRequest($request); + $query = $data['query'] ?? ''; + $variables = $data['variables'] ?? null; + + // We must extract queried field names to avoid instantiation of unnecessary fields in webonyx schema + // Temporal coupling is required for performance optimization + $this->queryFields->setQuery($query, $variables); + $schema = $this->schemaGenerator->generate(); + + $result = $this->queryProcessor->process( + $schema, + $query, + $this->resolverContext, + $data['variables'] ?? [] + ); } catch (\Exception $error) { $result['errors'] = isset($result) && isset($result['errors']) ? $result['errors'] : []; $result['errors'][] = $this->graphQlError->create($error); @@ -148,37 +141,22 @@ public function dispatch(RequestInterface $request) : ResponseInterface /** * Get data from request body or query string * - * @param Http $request + * @param RequestInterface $request * @return array */ - private function getDataFromRequest(Http $request) : array + private function getDataFromRequest(RequestInterface $request) : array { + /** @var Http $request */ if ($request->isPost()) { $data = $this->jsonSerializer->unserialize($request->getContent()); - } else { + } elseif ($request->isGet()) { $data = $request->getParams(); $data['variables'] = isset($data['variables']) ? $this->jsonSerializer->unserialize($data['variables']) : null; + } else { + return []; } return $data; } - - /** - * Check if request is using correct verb for query or mutation - * - * @param Http $request - * @return boolean - */ - private function isHttpVerbValid(Http $request) - { - $requestData = $this->getDataFromRequest($request); - $query = $requestData['query'] ?? ''; - - // The easiest way to determine mutations without additional parsing - if ($request->isSafeMethod() && strpos(trim($query), 'mutation') === 0) { - return false; - } - return true; - } } diff --git a/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/ContentTypeProcessor.php b/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/ContentTypeProcessor.php deleted file mode 100644 index 54d75eeae906a..0000000000000 --- a/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/ContentTypeProcessor.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\GraphQl\Controller\HttpHeaderProcessor; - -use Magento\Framework\App\HttpRequestInterface; -use Magento\Framework\Exception\LocalizedException; -use Magento\GraphQl\Controller\HttpHeaderProcessorInterface; - -/** - * Processes the "Content-Type" header entry - */ -class ContentTypeProcessor implements HttpHeaderProcessorInterface -{ - /** - * Handle the mandatory application/json header - * - * @param string $headerValue - * @param HttpRequestInterface $request - * @return void - * @throws LocalizedException - */ - public function processHeaderValue(string $headerValue, HttpRequestInterface $request) : void - { - if ($request->isPost() - && (!$headerValue || strpos($headerValue, 'application/json') === false) - ) { - throw new LocalizedException( - new \Magento\Framework\Phrase('Request content type must be application/json') - ); - } - } -} diff --git a/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php b/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php index c6121ac4b290f..246ad15379f85 100644 --- a/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php +++ b/app/code/Magento/GraphQl/Controller/HttpHeaderProcessor/StoreProcessor.php @@ -36,12 +36,10 @@ public function __construct(StoreManagerInterface $storeManager) * Handle the value of the store and set the scope * * @param string $headerValue - * @param HttpRequestInterface $request * @return void * @throws GraphQlInputException - * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function processHeaderValue(string $headerValue, HttpRequestInterface $request) : void + public function processHeaderValue(string $headerValue) : void { if ($headerValue) { $storeCode = ltrim(rtrim($headerValue)); diff --git a/app/code/Magento/GraphQl/Controller/HttpHeaderProcessorInterface.php b/app/code/Magento/GraphQl/Controller/HttpHeaderProcessorInterface.php index b38b96714eab2..a20f88a4ef995 100644 --- a/app/code/Magento/GraphQl/Controller/HttpHeaderProcessorInterface.php +++ b/app/code/Magento/GraphQl/Controller/HttpHeaderProcessorInterface.php @@ -7,8 +7,6 @@ namespace Magento\GraphQl\Controller; -use Magento\Framework\App\HttpRequestInterface; - /** * Use this interface to implement a processor for each entry of a header in an HTTP GraphQL request. */ @@ -21,8 +19,7 @@ interface HttpHeaderProcessorInterface * to enforce required headers like "application/json" * * @param string $headerValue - * @param HttpRequestInterface $request * @return void */ - public function processHeaderValue(string $headerValue, HttpRequestInterface $request) : void; + public function processHeaderValue(string $headerValue) : void; } diff --git a/app/code/Magento/GraphQl/Controller/HttpRequestProcessor.php b/app/code/Magento/GraphQl/Controller/HttpRequestProcessor.php index 5d1c970a358a3..bb29f1fa68af9 100644 --- a/app/code/Magento/GraphQl/Controller/HttpRequestProcessor.php +++ b/app/code/Magento/GraphQl/Controller/HttpRequestProcessor.php @@ -19,12 +19,19 @@ class HttpRequestProcessor */ private $headerProcessors = []; + /** + * @var HttpRequestValidatorInterface[] array + */ + private $requestValidators = []; + /** * @param HttpHeaderProcessorInterface[] $graphQlHeaders + * @param HttpRequestValidatorInterface[] $requestValidators */ - public function __construct(array $graphQlHeaders = []) + public function __construct(array $graphQlHeaders = [], array $requestValidators = []) { $this->headerProcessors = $graphQlHeaders; + $this->requestValidators = $requestValidators; } /** @@ -36,7 +43,20 @@ public function __construct(array $graphQlHeaders = []) public function processHeaders(Http $request) : void { foreach ($this->headerProcessors as $headerName => $headerClass) { - $headerClass->processHeaderValue((string)$request->getHeader($headerName), $request); + $headerClass->processHeaderValue((string)$request->getHeader($headerName)); + } + } + + /** + * Validate HTTP request + * + * @param Http $request + * @return void + */ + public function validateRequest(Http $request) : void + { + foreach ($this->requestValidators as $requestValidator) { + $requestValidator->validate($request); } } } diff --git a/app/code/Magento/GraphQl/Controller/HttpRequestValidator/ContentTypeValidator.php b/app/code/Magento/GraphQl/Controller/HttpRequestValidator/ContentTypeValidator.php new file mode 100644 index 0000000000000..555048aac6771 --- /dev/null +++ b/app/code/Magento/GraphQl/Controller/HttpRequestValidator/ContentTypeValidator.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Controller\HttpRequestValidator; + +use Magento\Framework\App\HttpRequestInterface; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\GraphQl\Controller\HttpRequestValidatorInterface; + +/** + * Processes the "Content-Type" header entry + */ +class ContentTypeValidator implements HttpRequestValidatorInterface +{ + /** + * Handle the mandatory application/json header + * + * @param HttpRequestInterface $request + * @return void + * @throws GraphQlInputException + */ + public function validate(HttpRequestInterface $request) : void + { + $headerName = 'Content-Type'; + $requiredHeaderValue = 'application/json'; + + $headerValue = (string)$request->getHeader($headerName); + if ($request->isPost() + && strpos($headerValue, $requiredHeaderValue) === false + ) { + throw new GraphQlInputException( + new \Magento\Framework\Phrase('Request content type must be application/json') + ); + } + } +} diff --git a/app/code/Magento/GraphQl/Controller/HttpRequestValidator/HttpVerbValidator.php b/app/code/Magento/GraphQl/Controller/HttpRequestValidator/HttpVerbValidator.php new file mode 100644 index 0000000000000..300b3d4f44dca --- /dev/null +++ b/app/code/Magento/GraphQl/Controller/HttpRequestValidator/HttpVerbValidator.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Controller\HttpRequestValidator; + +use Magento\Framework\App\HttpRequestInterface; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\Framework\App\Request\Http; +use Magento\GraphQl\Controller\HttpRequestValidatorInterface; + +/** + * Validator to check HTTP verb for Graphql requests + */ +class HttpVerbValidator implements HttpRequestValidatorInterface +{ + /** + * Check if request is using correct verb for query or mutation + * + * @param HttpRequestInterface $request + * @return void + * @throws GraphQlInputException + */ + public function validate(HttpRequestInterface $request) : void + { + /** @var Http $request */ + if (false === $request->isPost()) { + $query = $request->getParam('query', ''); + // The easiest way to determine mutations without additional parsing + if (strpos(trim($query), 'mutation') === 0) { + throw new GraphQlInputException( + new \Magento\Framework\Phrase('Mutation requests allowed only for POST requests') + ); + } + } + } +} diff --git a/app/code/Magento/GraphQl/Controller/HttpRequestValidatorInterface.php b/app/code/Magento/GraphQl/Controller/HttpRequestValidatorInterface.php new file mode 100644 index 0000000000000..c0873b0caff89 --- /dev/null +++ b/app/code/Magento/GraphQl/Controller/HttpRequestValidatorInterface.php @@ -0,0 +1,24 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Controller; + +use Magento\Framework\App\HttpRequestInterface; + +/** + * Use this interface to implement a validator for a Graphql HTTP requests + */ +interface HttpRequestValidatorInterface +{ + /** + * Perform validation of request + * + * @param HttpRequestInterface $request + * @return void + */ + public function validate(HttpRequestInterface $request) : void; +} diff --git a/app/code/Magento/GraphQl/etc/graphql/di.xml b/app/code/Magento/GraphQl/etc/graphql/di.xml index f4e6ca59364b2..b4f0113f58776 100644 --- a/app/code/Magento/GraphQl/etc/graphql/di.xml +++ b/app/code/Magento/GraphQl/etc/graphql/di.xml @@ -28,9 +28,12 @@ <type name="Magento\GraphQl\Controller\HttpRequestProcessor"> <arguments> <argument name="graphQlHeaders" xsi:type="array"> - <item name="Content-Type" xsi:type="object">Magento\GraphQl\Controller\HttpHeaderProcessor\ContentTypeProcessor</item> <item name="Store" xsi:type="object">Magento\GraphQl\Controller\HttpHeaderProcessor\StoreProcessor</item> </argument> + <argument name="requestValidators" xsi:type="array"> + <item name="ContentTypeValidator" xsi:type="object">Magento\GraphQl\Controller\HttpRequestValidator\ContentTypeValidator</item> + <item name="VerbValidator" xsi:type="object">Magento\GraphQl\Controller\HttpRequestValidator\HttpVerbValidator</item> + </argument> </arguments> </type> </config> diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php index 6ace9b557ff9f..5eea3be840ae5 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php @@ -51,7 +51,7 @@ public function __construct( * @return array|string|int|float|bool * @throws \Exception */ - public function postQuery(string $query, array $variables = [], string $operationName = '', array $headers = []) + public function post(string $query, array $variables = [], string $operationName = '', array $headers = []) { $url = $this->getEndpointUrl(); $headers = array_merge($headers, ['Accept: application/json', 'Content-Type: application/json']); @@ -63,19 +63,7 @@ public function postQuery(string $query, array $variables = [], string $operatio $postData = $this->json->jsonEncode($requestArray); $responseBody = $this->curlClient->post($url, $postData, $headers); - $responseBodyArray = $this->json->jsonDecode($responseBody); - - if (!is_array($responseBodyArray)) { - throw new \Exception('Unknown GraphQL response body: ' . json_encode($responseBodyArray)); - } - - $this->processErrors($responseBodyArray); - - if (!isset($responseBodyArray['data'])) { - throw new \Exception('Unknown GraphQL response body: ' . json_encode($responseBodyArray)); - } else { - return $responseBodyArray['data']; - } + return $this->processResponse($responseBody); } /** @@ -88,7 +76,7 @@ public function postQuery(string $query, array $variables = [], string $operatio * @return mixed * @throws \Exception */ - public function getQuery(string $query, array $variables = [], string $operationName = '', array $headers = []) + public function get(string $query, array $variables = [], string $operationName = '', array $headers = []) { $url = $this->getEndpointUrl(); $requestArray = [ @@ -98,19 +86,31 @@ public function getQuery(string $query, array $variables = [], string $operation ]; $responseBody = $this->curlClient->get($url, $requestArray, $headers); - $responseBodyArray = $this->json->jsonDecode($responseBody); + return $this->processResponse($responseBody); + } + + /** + * Process response from GraphQl server + * + * @param string $response + * @return mixed + * @throws \Exception + */ + private function processResponse(string $response) + { + $responseArray = $this->json->jsonDecode($response); - if (!is_array($responseBodyArray)) { - throw new \Exception('Unknown GraphQL response body: ' . json_encode($responseBodyArray)); + if (!is_array($responseArray)) { + throw new \Exception('Unknown GraphQL response body: ' . $response); } - $this->processErrors($responseBodyArray); + $this->processErrors($responseArray); - if (!isset($responseBodyArray['data'])) { - throw new \Exception('Unknown GraphQL response body: ' . json_encode($responseBodyArray)); - } else { - return $responseBodyArray['data']; + if (!isset($responseArray['data'])) { + throw new \Exception('Unknown GraphQL response body: ' . $response); } + + return $responseArray['data']; } /** diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php index d1a6356d78fba..8abd97b4b744d 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQlAbstract.php @@ -28,14 +28,13 @@ abstract class GraphQlAbstract extends WebapiAbstract private $appCache; /** - * Perform GraphQL call to the system under test. + * Perform GraphQL query call via GET to the system under test. * * @see \Magento\TestFramework\TestCase\GraphQl\Client::call() * @param string $query * @param array $variables * @param string $operationName * @param array $headers - * @param string $requestType * @return array|int|string|float|bool GraphQL call results * @throws \Exception */ @@ -43,28 +42,39 @@ public function graphQlQuery( string $query, array $variables = [], string $operationName = '', - array $headers = [], - string $requestType = Http::METHOD_POST + array $headers = [] ) { - if ($requestType === Http::METHOD_POST) { - $response = $this->getGraphQlClient()->postQuery( - $query, - $variables, - $operationName, - $this->composeHeaders($headers) - ); - } elseif ($requestType === Http::METHOD_GET) { - $response = $this->getGraphQlClient()->getQuery( - $query, - $variables, - $operationName, - $this->composeHeaders($headers) - ); - } else { - throw new \Exception("Unsupported request type"); - } + return $this->getGraphQlClient()->get( + $query, + $variables, + $operationName, + $this->composeHeaders($headers) + ); + } - return $response; + /** + * Perform GraphQL mutations call via POST to the system under test. + * + * @see \Magento\TestFramework\TestCase\GraphQl\Client::call() + * @param string $query + * @param array $variables + * @param string $operationName + * @param array $headers + * @return array|int|string|float|bool GraphQL call results + * @throws \Exception + */ + public function graphQlMutation( + string $query, + array $variables = [], + string $operationName = '', + array $headers = [] + ) { + return $this->getGraphQlClient()->post( + $query, + $variables, + $operationName, + $this->composeHeaders($headers) + ); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 17c2af8dc59d0..0e7ada49dfd38 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -54,7 +54,7 @@ public function testAddProductIfQuantityIsNotAvailable() $maskedQuoteId = $this->getMaskedQuoteId(); $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); - $this->graphQlQuery($query); + $this->graphQlMutation($query); self::fail('Should be "The requested qty is not available" error message.'); } @@ -74,7 +74,7 @@ public function testAddMoreProductsThatAllowed() $maskedQuoteId = $this->getMaskedQuoteId(); $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); - $this->graphQlQuery($query); + $this->graphQlMutation($query); self::fail('Should be "The most you may purchase is 5." error message.'); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ChangeCustomerPasswordTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ChangeCustomerPasswordTest.php index 84c111bd25fd4..d147229f55a2d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ChangeCustomerPasswordTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ChangeCustomerPasswordTest.php @@ -50,7 +50,7 @@ public function testChangePassword() $query = $this->getChangePassQuery($oldCustomerPassword, $newCustomerPassword); $headerMap = $this->getCustomerAuthHeaders($customerEmail, $oldCustomerPassword); - $response = $this->graphQlQuery($query, [], '', $headerMap); + $response = $this->graphQlMutation($query, [], '', $headerMap); $this->assertEquals($customerEmail, $response['changeCustomerPassword']['email']); try { @@ -69,7 +69,7 @@ public function testChangePassword() public function testChangePasswordIfUserIsNotAuthorizedTest() { $query = $this->getChangePassQuery('currentpassword', 'newpassword'); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -87,7 +87,7 @@ public function testChangeWeakPassword() $this->expectException(\Exception::class); $this->expectExceptionMessageRegExp('/Minimum of different classes of characters in password is.*/'); - $this->graphQlQuery($query, [], '', $headerMap); + $this->graphQlMutation($query, [], '', $headerMap); } /** @@ -105,7 +105,7 @@ public function testChangePasswordIfPasswordIsInvalid() $query = $this->getChangePassQuery($incorrectPassword, $newCustomerPassword); $headerMap = $this->getCustomerAuthHeaders($customerEmail, $oldCustomerPassword); - $this->graphQlQuery($query, [], '', $headerMap); + $this->graphQlMutation($query, [], '', $headerMap); } private function getChangePassQuery($currentPassword, $newPassword) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php index 602d969924fbd..5019bd0f50c80 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php @@ -117,7 +117,7 @@ public function testCreateCustomerAddress() $userName = 'customer@example.com'; $password = 'password'; - $response = $this->graphQlQuery($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); + $response = $this->graphQlMutation($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); $this->assertArrayHasKey('createCustomerAddress', $response); $this->assertArrayHasKey('customer_id', $response['createCustomerAddress']); $this->assertEquals($customerId, $response['createCustomerAddress']['customer_id']); @@ -158,7 +158,7 @@ public function testCreateCustomerAddressIfUserIsNotAuthorized() } } MUTATION; - $this->graphQlQuery($mutation); + $this->graphQlMutation($mutation); } /** @@ -195,7 +195,7 @@ public function testCreateCustomerAddressWithMissingAttribute() $userName = 'customer@example.com'; $password = 'password'; - $this->graphQlQuery($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); + $this->graphQlMutation($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerTest.php index 388028c4ca750..fc51f57a83a76 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerTest.php @@ -66,7 +66,7 @@ public function testCreateCustomerAccountWithPassword() } } QUERY; - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); $this->assertEquals($newFirstname, $response['createCustomer']['customer']['firstname']); $this->assertEquals($newLastname, $response['createCustomer']['customer']['lastname']); @@ -103,7 +103,7 @@ public function testCreateCustomerAccountWithoutPassword() } } QUERY; - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); $this->assertEquals($newFirstname, $response['createCustomer']['customer']['firstname']); $this->assertEquals($newLastname, $response['createCustomer']['customer']['lastname']); @@ -134,7 +134,7 @@ public function testCreateCustomerIfInputDataIsEmpty() } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -167,7 +167,7 @@ public function testCreateCustomerIfEmailMissed() } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -202,7 +202,7 @@ public function testCreateCustomerIfEmailIsNotValid() } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -238,7 +238,7 @@ public function testCreateCustomerIfPassedAttributeDosNotExistsInCustomerInput() } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } public function tearDown() diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/DeleteCustomerAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/DeleteCustomerAddressTest.php index 1153b9662b41a..c25d8a7183514 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/DeleteCustomerAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/DeleteCustomerAddressTest.php @@ -55,7 +55,7 @@ public function testDeleteCustomerAddress() deleteCustomerAddress(id: {$addressId}) } MUTATION; - $response = $this->graphQlQuery($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); + $response = $this->graphQlMutation($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); $this->assertArrayHasKey('deleteCustomerAddress', $response); $this->assertEquals(true, $response['deleteCustomerAddress']); } @@ -73,7 +73,7 @@ public function testDeleteCustomerAddressIfUserIsNotAuthorized() deleteCustomerAddress(id: {$addressId}) } MUTATION; - $this->graphQlQuery($mutation); + $this->graphQlMutation($mutation); } /** @@ -99,7 +99,7 @@ public function testDeleteDefaultShippingCustomerAddress() deleteCustomerAddress(id: {$addressId}) } MUTATION; - $this->graphQlQuery($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); + $this->graphQlMutation($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); } /** @@ -125,7 +125,7 @@ public function testDeleteDefaultBillingCustomerAddress() deleteCustomerAddress(id: {$addressId}) } MUTATION; - $this->graphQlQuery($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); + $this->graphQlMutation($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); } /** @@ -144,7 +144,7 @@ public function testDeleteNonExistCustomerAddress() deleteCustomerAddress(id: 9999) } MUTATION; - $this->graphQlQuery($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); + $this->graphQlMutation($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php index ae28e23a28bf1..88eaeaa8f9dd5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php @@ -38,7 +38,7 @@ public function testGenerateCustomerValidToken() } MUTATION; - $response = $this->graphQlQuery($mutation); + $response = $this->graphQlMutation($mutation); $this->assertArrayHasKey('generateCustomerToken', $response); $this->assertInternalType('array', $response['generateCustomerToken']); } @@ -66,6 +66,6 @@ public function testGenerateCustomerTokenWithInvalidCredentials() $this->expectException(\Exception::class); $this->expectExceptionMessage('GraphQL response contains errors: The account sign-in' . ' ' . 'was incorrect or your account is disabled temporarily. Please wait and try again later.'); - $this->graphQlQuery($mutation); + $this->graphQlMutation($mutation); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/RevokeCustomerTokenTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/RevokeCustomerTokenTest.php index 9bdbf3059eeaf..fc0c02bae5508 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/RevokeCustomerTokenTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/RevokeCustomerTokenTest.php @@ -36,7 +36,7 @@ public function testRevokeCustomerTokenValidCredentials() $customerToken = $customerTokenService->createCustomerAccessToken($userName, $password); $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; - $response = $this->graphQlQuery($query, [], '', $headerMap); + $response = $this->graphQlMutation($query, [], '', $headerMap); $this->assertTrue($response['revokeCustomerToken']['result']); } @@ -53,6 +53,6 @@ public function testRevokeCustomerTokenForGuestCustomer() } } QUERY; - $this->graphQlQuery($query, [], ''); + $this->graphQlMutation($query, [], ''); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/SubscriptionStatusTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/SubscriptionStatusTest.php index 191ea1ae6b877..6d9782dae87d4 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/SubscriptionStatusTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/SubscriptionStatusTest.php @@ -88,7 +88,12 @@ public function testChangeSubscriptionStatusTest() } } QUERY; - $response = $this->graphQlQuery($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); + $response = $this->graphQlMutation( + $query, + [], + '', + $this->getCustomerAuthHeaders($currentEmail, $currentPassword) + ); $this->assertTrue($response['updateCustomer']['customer']['is_subscribed']); } @@ -111,7 +116,7 @@ public function testChangeSubscriptionStatuIfUserIsNotAuthorizedTest() } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerAddressTest.php index 6a9708b4f86a2..bfb07ccf4149c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerAddressTest.php @@ -128,7 +128,7 @@ public function testUpdateCustomerAddress() } MUTATION; - $response = $this->graphQlQuery($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); + $response = $this->graphQlMutation($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); $this->assertArrayHasKey('updateCustomerAddress', $response); $this->assertArrayHasKey('customer_id', $response['updateCustomerAddress']); $this->assertEquals($customerId, $response['updateCustomerAddress']['customer_id']); @@ -158,7 +158,7 @@ public function testUpdateCustomerAddressIfUserIsNotAuthorized() } } MUTATION; - $this->graphQlQuery($mutation); + $this->graphQlMutation($mutation); } /** @@ -187,7 +187,7 @@ public function testUpdateCustomerAddressWithMissingAttribute() } } MUTATION; - $this->graphQlQuery($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); + $this->graphQlMutation($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php index df45e1de771d9..53c20ad898505 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php @@ -87,7 +87,7 @@ public function testUpdateCustomer() } } QUERY; - $response = $this->graphQlQuery($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); + $response = $this->graphQlMutation($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); $this->assertEquals($newPrefix, $response['updateCustomer']['customer']['prefix']); $this->assertEquals($newFirstname, $response['updateCustomer']['customer']['firstname']); @@ -123,7 +123,7 @@ public function testUpdateCustomerIfInputDataIsEmpty() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); + $this->graphQlMutation($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); } /** @@ -147,7 +147,7 @@ public function testUpdateCustomerIfUserIsNotAuthorized() } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -176,7 +176,7 @@ public function testUpdateCustomerIfAccountIsLocked() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); + $this->graphQlMutation($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); } /** @@ -203,7 +203,7 @@ public function testUpdateEmailIfPasswordIsMissed() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); + $this->graphQlMutation($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); } /** @@ -232,7 +232,7 @@ public function testUpdateEmailIfPasswordIsInvalid() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); + $this->graphQlMutation($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); } /** @@ -260,7 +260,7 @@ public function testUpdateEmailIfEmailAlreadyExists() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); + $this->graphQlMutation($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddConfigurableProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddConfigurableProductToCartTest.php index b3f16c8734203..d8df8db800d8c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddConfigurableProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddConfigurableProductToCartTest.php @@ -54,7 +54,7 @@ public function testAddConfigurableProductToCart() $query = $this->getAddConfigurableProductMutationQuery($maskedQuoteId, $variantSku, $qty); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); $cartItems = $response['addConfigurableProductsToCart']['cart']['items']; self::assertEquals($qty, $cartItems[0]['qty']); self::assertEquals($variantSku, $cartItems[0]['product']['sku']); @@ -74,7 +74,7 @@ public function testAddProductIfQuantityIsNotAvailable() $maskedQuoteId = $this->getMaskedQuoteId(); $query = $this->getAddConfigurableProductMutationQuery($maskedQuoteId, $variantSku, $qty); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -90,7 +90,7 @@ public function testAddOutOfStockProduct() $maskedQuoteId = $this->getMaskedQuoteId(); $query = $this->getAddConfigurableProductMutationQuery($maskedQuoteId, $variantSku, $qty); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php index d9ab8db62a195..4334a3d6785d6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php @@ -52,7 +52,7 @@ public function testAddSimpleProductToCart() $maskedQuoteId = $this->getMaskedQuoteId(); $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['qty']); @@ -72,7 +72,7 @@ public function testAddSimpleProductToCartWithNegativeQty() $maskedQuoteId = $this->getMaskedQuoteId(); $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -158,6 +158,6 @@ public function testAddProductWithWrongCartHash() } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/CouponTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/CouponTest.php index 828784ca27885..2f0fc7cc04bc9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/CouponTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/CouponTest.php @@ -56,7 +56,7 @@ public function testApplyCouponToGuestCartWithItems() ); $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('applyCouponToCart', $response); self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); @@ -77,13 +77,13 @@ public function testApplyCouponTwice() ); $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey("applyCouponToCart", $response); self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); self::expectExceptionMessage('A coupon is already applied to the cart. Please remove it to apply another'); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -100,7 +100,7 @@ public function testApplyCouponToCartWithNoItems() $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -123,7 +123,7 @@ public function testGuestCustomerAttemptToChangeCustomerCart() $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -147,11 +147,11 @@ public function testRemoveCoupon() 'reserved_order_id' ); $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query); + $this->graphQlMutation($query); /* Remove coupon from quote */ $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('removeCouponFromCart', $response); self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); @@ -180,7 +180,7 @@ public function testRemoveCouponFromCustomerCartByGuest() $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php index 0cb8a38b0cb5e..0091354a6ee65 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php @@ -48,7 +48,7 @@ public function testCreateEmptyCart() $customerToken = $this->customerTokenService->createCustomerAccessToken('customer@example.com', 'password'); $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; - $response = $this->graphQlQuery($query, [], '', $headerMap); + $response = $this->graphQlMutation($query, [], '', $headerMap); self::assertArrayHasKey('createEmptyCart', $response); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php index e80a2127ad420..468f0d34a14dd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php @@ -66,7 +66,7 @@ public function testRemoveItemFromCart() $itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId(); $query = $this->prepareMutationQuery($maskedQuoteId, $itemId); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); $this->assertArrayHasKey('removeItemFromCart', $response); $this->assertArrayHasKey('cart', $response['removeItemFromCart']); @@ -81,7 +81,7 @@ public function testRemoveItemFromCart() public function testRemoveItemFromNonExistentCart() { $query = $this->prepareMutationQuery('non_existent_masked_id', 1); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -97,7 +97,7 @@ public function testRemoveNonExistentItem() $this->expectExceptionMessage("Cart doesn't contain the {$notExistentItemId} item."); $query = $this->prepareMutationQuery($maskedQuoteId, $notExistentItemId); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -125,7 +125,7 @@ public function testRemoveItemIfItemIsNotBelongToCart() $this->expectExceptionMessage("Cart doesn't contain the {$secondQuoteItemId} item."); $query = $this->prepareMutationQuery($firstQuoteMaskedId, $secondQuoteItemId); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -150,7 +150,7 @@ public function testRemoveItemFromGuestCart() ); $query = $this->prepareMutationQuery($guestQuoteMaskedId, $guestQuoteItemId); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -179,7 +179,7 @@ public function testRemoveItemFromAnotherCustomerCart() ); $query = $this->prepareMutationQuery($anotherCustomerQuoteMaskedId, $anotherCustomerQuoteItemId); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -206,7 +206,7 @@ public function testUpdateWithMissedItemRequiredParameters(string $input, string } QUERY; $this->expectExceptionMessage($message); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php index 88e7b93dd1d08..94e347cd46f08 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php @@ -105,7 +105,7 @@ public function testSetNewBillingAddress() } } QUERY; - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['setBillingAddressOnCart']); $cartResponse = $response['setBillingAddressOnCart']['cart']; @@ -179,7 +179,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() } } QUERY; - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['setBillingAddressOnCart']); $cartResponse = $response['setBillingAddressOnCart']['cart']; @@ -230,7 +230,7 @@ public function testSetBillingAddressFromAddressBook() } } QUERY; - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['setBillingAddressOnCart']); $cartResponse = $response['setBillingAddressOnCart']['cart']; @@ -270,7 +270,7 @@ public function testSetNotExistedBillingAddressFromAddressBook() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -318,7 +318,7 @@ public function testSetNewBillingAddressAndFromAddressBookAtSameTime() self::expectExceptionMessage( 'The billing address cannot contain "customer_address_id" and "address" at the same time.' ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -355,7 +355,7 @@ public function testSetBillingAddressToGuestCart() "The current user cannot perform operations on cart \"{$maskedQuoteId}\"" ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -390,7 +390,7 @@ public function testSetBillingAddressToAnotherCustomerCart() "The current user cannot perform operations on cart \"{$maskedQuoteId}\"" ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer@search.example.com')); + $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer@search.example.com')); } /** @@ -424,7 +424,7 @@ public function testSetBillingAddressIfCustomerIsNotOwnerOfAddress() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer2@search.example.com')); + $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer2@search.example.com')); } /** @@ -454,7 +454,7 @@ public function testSetBillingAddressOnNonExistentCart() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -490,7 +490,7 @@ public function testSetBillingAddressWithoutRequiredParameters(string $input, st QUERY; $this->expectExceptionMessage($message); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php index bd147cc4a197e..baa929768527d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php @@ -72,7 +72,7 @@ public function testSetOfflineShippingMethod(string $carrierCode, string $method $carrierCode, $quoteAddressId ); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('setShippingMethodsOnCart', $response); self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php index 98eded8300665..189a470bfac78 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php @@ -52,7 +52,7 @@ public function testSetPaymentOnCartWithSimpleProduct() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $methodCode); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); @@ -75,7 +75,7 @@ public function testSetPaymentOnCartWithSimpleProductAndWithoutAddress() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $methodCode); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -90,7 +90,7 @@ public function testSetPaymentOnCartWithVirtualProduct() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $methodCode); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); @@ -114,7 +114,7 @@ public function testSetNonExistentPaymentMethod() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $methodCode); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -129,7 +129,7 @@ public function testSetPaymentOnNonExistentCart() $methodCode = Checkmo::PAYMENT_METHOD_CHECKMO_CODE; $query = $this->getQuery($maskedQuoteId, $methodCode); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -149,7 +149,7 @@ public function testSetPaymentMethodToGuestCart() $this->expectExceptionMessage( "The current user cannot perform operations on cart \"$maskedQuoteId\"" ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -169,7 +169,7 @@ public function testSetPaymentMethodToAnotherCustomerCart() $this->expectExceptionMessage( "The current user cannot perform operations on cart \"$maskedQuoteId\"" ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer2@search.example.com')); + $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer2@search.example.com')); } /** @@ -201,7 +201,7 @@ public function testSetPaymentMethodWithoutRequiredParameters(string $input, str } QUERY; $this->expectExceptionMessage($message); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -240,7 +240,7 @@ public function testReSetPayment() $methodCode = Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE; $query = $this->getQuery($maskedQuoteId, $methodCode); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php index 5ff29d20b34d7..70db0d1e66a54 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php @@ -107,7 +107,7 @@ public function testSetNewShippingAddressOnCartWithSimpleProduct() } } QUERY; - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']); $cartResponse = $response['setShippingAddressesOnCart']['cart']; @@ -160,7 +160,7 @@ public function testSetNewShippingAddressOnCartWithVirtualProduct() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -200,7 +200,7 @@ public function testSetShippingAddressFromAddressBook() } } QUERY; - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']); $cartResponse = $response['setShippingAddressesOnCart']['cart']; @@ -242,7 +242,7 @@ public function testSetNonExistentShippingAddressFromAddressBook() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -291,7 +291,7 @@ public function testSetNewShippingAddressAndFromAddressBookAtSameTime() self::expectExceptionMessage( 'The shipping address cannot contain "customer_address_id" and "address" at the same time.' ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -328,7 +328,7 @@ public function testSetShippingAddressIfCustomerIsNotOwnerOfAddress() } QUERY; - $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer2@search.example.com')); + $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer2@search.example.com')); } /** @@ -366,7 +366,7 @@ public function testSetShippingAddressToAnotherCustomerCart() $this->expectExceptionMessage( "The current user cannot perform operations on cart \"$maskedQuoteId\"" ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer2@search.example.com')); + $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer2@search.example.com')); } /** @@ -405,7 +405,7 @@ public function testSetNewShippingAddressWithMissedRequiredParameters(string $in } QUERY; $this->expectExceptionMessage($message); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -483,7 +483,7 @@ public function testSetMultipleNewShippingAddresses() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php index 29ddbefd8e405..4e048c7502639 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php @@ -66,7 +66,7 @@ public function testSetShippingMethodOnCartWithSimpleProduct() $carrierCode, $quoteAddressId ); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('setShippingMethodsOnCart', $response); self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); @@ -105,7 +105,7 @@ public function testReSetShippingMethod() $carrierCode, $quoteAddressId ); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('setShippingMethodsOnCart', $response); self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); @@ -156,7 +156,7 @@ public function testSetShippingMethodWithWrongParameters(string $input, string $ } QUERY; $this->expectExceptionMessage($message); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -296,7 +296,7 @@ public function testSetMultipleShippingMethods() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -325,7 +325,7 @@ public function testSetShippingMethodToGuestCart() $this->expectExceptionMessage( "The current user cannot perform operations on cart \"$maskedQuoteId\"" ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -354,7 +354,7 @@ public function testSetShippingMethodToAnotherCustomerCart() $this->expectExceptionMessage( "The current user cannot perform operations on cart \"$maskedQuoteId\"" ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer2@search.example.com')); + $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer2@search.example.com')); } /** @@ -382,7 +382,7 @@ public function testSetShippingMethodIfCustomerIsNotOwnerOfAddress() $this->expectExceptionMessage( "Cart does not contain address with ID \"{$anotherQuoteAddressId}\"" ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php index 74e7aa8b5d0a4..35e2d62214fb2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php @@ -67,7 +67,7 @@ public function testUpdateCartItemQty() $qty = 2; $query = $this->getQuery($maskedQuoteId, $itemId, $qty); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); $this->assertArrayHasKey('updateCartItems', $response); $this->assertArrayHasKey('cart', $response['updateCartItems']); @@ -91,7 +91,7 @@ public function testRemoveCartItemIfQuantityIsZero() $qty = 0; $query = $this->getQuery($maskedQuoteId, $itemId, $qty); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); $this->assertArrayHasKey('updateCartItems', $response); $this->assertArrayHasKey('cart', $response['updateCartItems']); @@ -108,7 +108,7 @@ public function testRemoveCartItemIfQuantityIsZero() public function testUpdateItemInNonExistentCart() { $query = $this->getQuery('non_existent_masked_id', 1, 2); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -124,7 +124,7 @@ public function testUpdateNonExistentItem() $this->expectExceptionMessage("Could not find cart item with id: {$notExistentItemId}."); $query = $this->getQuery($maskedQuoteId, $notExistentItemId, 2); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -152,7 +152,7 @@ public function testUpdateItemIfItemIsNotBelongToCart() $this->expectExceptionMessage("Could not find cart item with id: {$secondQuoteItemId}."); $query = $this->getQuery($firstQuoteMaskedId, $secondQuoteItemId, 2); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -177,7 +177,7 @@ public function testUpdateItemInGuestCart() ); $query = $this->getQuery($guestQuoteMaskedId, $guestQuoteItemId, 2); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -206,7 +206,7 @@ public function testUpdateItemInAnotherCustomerCart() ); $query = $this->getQuery($anotherCustomerQuoteMaskedId, $anotherCustomerQuoteItemId, 2); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -235,7 +235,7 @@ public function testUpdateWithMissedCartItemId() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -266,7 +266,7 @@ public function testUpdateWithMissedItemRequiredParameters(string $input, string } QUERY; $this->expectExceptionMessage($message); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php index 4fd398439913e..c74eb3d06f6ff 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php @@ -34,7 +34,7 @@ public function testCreateEmptyCart() createEmptyCart } QUERY; - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('createEmptyCart', $response); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php index a306b29e51197..cfb041b4d797e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php @@ -59,7 +59,7 @@ public function testRemoveItemFromCart() $itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId(); $query = $this->prepareMutationQuery($maskedQuoteId, $itemId); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); $this->assertArrayHasKey('removeItemFromCart', $response); $this->assertArrayHasKey('cart', $response['removeItemFromCart']); @@ -73,7 +73,7 @@ public function testRemoveItemFromCart() public function testRemoveItemFromNonExistentCart() { $query = $this->prepareMutationQuery('non_existent_masked_id', 1); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -89,7 +89,7 @@ public function testRemoveNonExistentItem() $this->expectExceptionMessage("Cart doesn't contain the {$notExistentItemId} item."); $query = $this->prepareMutationQuery($maskedQuoteId, $notExistentItemId); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -117,7 +117,7 @@ public function testRemoveItemIfItemIsNotBelongToCart() $this->expectExceptionMessage("Cart doesn't contain the {$secondQuoteItemId} item."); $query = $this->prepareMutationQuery($firstQuoteMaskedId, $secondQuoteItemId); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -135,7 +135,7 @@ public function testRemoveItemFromCustomerCart() $this->expectExceptionMessage("The current user cannot perform operations on cart \"$customerQuoteMaskedId\""); $query = $this->prepareMutationQuery($customerQuoteMaskedId, $customerQuoteItemId); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -161,7 +161,7 @@ public function testUpdateWithMissedItemRequiredParameters(string $input, string } QUERY; $this->expectExceptionMessage($message); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php index ae0a1a0e822ac..c6572e9898c3d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php @@ -76,7 +76,7 @@ public function testSetNewBillingAddress() } } QUERY; - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('cart', $response['setBillingAddressOnCart']); $cartResponse = $response['setBillingAddressOnCart']['cart']; @@ -149,7 +149,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() } } QUERY; - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('cart', $response['setBillingAddressOnCart']); $cartResponse = $response['setBillingAddressOnCart']['cart']; @@ -203,7 +203,7 @@ public function testSetBillingAddressToCustomerCart() $this->expectExceptionMessage( "The current user cannot perform operations on cart \"$maskedQuoteId\"" ); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -237,7 +237,7 @@ public function testSetBillingAddressFromAddressBook() } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -276,7 +276,7 @@ public function testSetBillingAddressOnNonExistentCart() } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -310,7 +310,7 @@ public function testSetBillingAddressWithoutRequiredParameters(string $input, st } QUERY; $this->expectExceptionMessage($message); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php index 8ed9ef84d6fbd..264cacda31375 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php @@ -64,7 +64,7 @@ public function testSetOfflineShippingMethod(string $carrierCode, string $method $carrierCode, $quoteAddressId ); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('setShippingMethodsOnCart', $response); self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php index c9078fd84f6bc..f0e9d57f0f315 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php @@ -44,7 +44,7 @@ public function testSetPaymentOnCartWithSimpleProduct() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $methodCode); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); @@ -66,7 +66,7 @@ public function testSetPaymentOnCartWithSimpleProductAndWithoutAddress() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $methodCode); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -80,7 +80,7 @@ public function testSetPaymentOnCartWithVirtualProduct() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $methodCode); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); @@ -103,7 +103,7 @@ public function testSetNonExistentPaymentMethod() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $methodCode); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -116,7 +116,7 @@ public function testSetPaymentOnNonExistentCart() $methodCode = Checkmo::PAYMENT_METHOD_CHECKMO_CODE; $query = $this->getQuery($maskedQuoteId, $methodCode); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -137,7 +137,7 @@ public function testSetPaymentMethodToCustomerCart() $this->expectExceptionMessage( "The current user cannot perform operations on cart \"$maskedQuoteId\"" ); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -169,7 +169,7 @@ public function testSetPaymentMethodWithoutRequiredParameters(string $input, str } QUERY; $this->expectExceptionMessage($message); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -207,7 +207,7 @@ public function testReSetPayment() $methodCode = Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE; $query = $this->getQuery($maskedQuoteId, $methodCode); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php index e21d9ed64d491..4c7dfe03a0b44 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php @@ -78,7 +78,7 @@ public function testSetNewShippingAddressOnCartWithSimpleProduct() } } QUERY; - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']); $cartResponse = $response['setShippingAddressesOnCart']['cart']; @@ -130,7 +130,7 @@ public function testSetNewShippingAddressOnCartWithVirtualProduct() } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -166,7 +166,7 @@ public function testSetShippingAddressFromAddressBook() } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -205,7 +205,7 @@ public function testSetShippingAddressToCustomerCart() $this->expectExceptionMessage( "The current user cannot perform operations on cart \"$maskedQuoteId\"" ); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -243,7 +243,7 @@ public function testSetNewShippingAddressWithMissedRequiredParameters(string $in } QUERY; $this->expectExceptionMessage($message); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -320,7 +320,7 @@ public function testSetMultipleNewShippingAddresses() } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php index ca26f8fe5aaf0..e8ca6131d2616 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php @@ -58,7 +58,7 @@ public function testSetShippingMethodOnCartWithSimpleProduct() $carrierCode, $quoteAddressId ); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('setShippingMethodsOnCart', $response); self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); @@ -101,7 +101,7 @@ public function testSetShippingMethodOnCartWithSimpleProductAndWithoutAddress() $carrierCode, $quoteAddressId ); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -125,7 +125,7 @@ public function testReSetShippingMethod() $carrierCode, $quoteAddressId ); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('setShippingMethodsOnCart', $response); self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); @@ -175,7 +175,7 @@ public function testSetShippingMethodWithWrongParameters(string $input, string $ } QUERY; $this->expectExceptionMessage($message); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -314,7 +314,7 @@ public function testSetMultipleShippingMethods() } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -343,7 +343,7 @@ public function testSetShippingMethodToCustomerCart() $this->expectExceptionMessage( "The current user cannot perform operations on cart \"$maskedQuoteId\"" ); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -370,7 +370,7 @@ public function testSetShippingMethodIfGuestIsNotOwnerOfAddress() $this->expectExceptionMessage( "Cart does not contain address with ID \"{$anotherQuoteAddressId}\"" ); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php index fca7a4287620b..1b8cf2e1c57f7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php @@ -60,7 +60,7 @@ public function testUpdateCartItemQty() $qty = 2; $query = $this->getQuery($maskedQuoteId, $itemId, $qty); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); $this->assertArrayHasKey('updateCartItems', $response); $this->assertArrayHasKey('cart', $response['updateCartItems']); @@ -84,7 +84,7 @@ public function testRemoveCartItemIfQuantityIsZero() $qty = 0; $query = $this->getQuery($maskedQuoteId, $itemId, $qty); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); $this->assertArrayHasKey('updateCartItems', $response); $this->assertArrayHasKey('cart', $response['updateCartItems']); @@ -100,7 +100,7 @@ public function testRemoveCartItemIfQuantityIsZero() public function testUpdateItemInNonExistentCart() { $query = $this->getQuery('non_existent_masked_id', 1, 2); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -116,7 +116,7 @@ public function testUpdateNonExistentItem() $this->expectExceptionMessage("Could not find cart item with id: {$notExistentItemId}."); $query = $this->getQuery($maskedQuoteId, $notExistentItemId, 2); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -142,7 +142,7 @@ public function testUpdateItemIfItemIsNotBelongToCart() $this->expectExceptionMessage("Could not find cart item with id: {$secondQuoteItemId}."); $query = $this->getQuery($firstQuoteMaskedId, $secondQuoteItemId, 2); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -158,7 +158,7 @@ public function testUpdateItemFromCustomerCart() $this->expectExceptionMessage("The current user cannot perform operations on cart \"$customerQuoteMaskedId\""); $query = $this->getQuery($customerQuoteMaskedId, $customerQuoteItemId, 2); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -186,7 +186,7 @@ public function testUpdateWithMissedCartItemId() } } QUERY; - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -217,7 +217,7 @@ public function testUpdateWithMissedItemRequiredParameters(string $input, string } QUERY; $this->expectExceptionMessage($message); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/SendFriend/SendFriendTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/SendFriend/SendFriendTest.php index 05e3e608c5e52..b40a2b787fe81 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/SendFriend/SendFriendTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/SendFriend/SendFriendTest.php @@ -66,7 +66,7 @@ public function testSendFriend() } QUERY; - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertEquals('Name', $response['sendEmailToFriend']['sender']['name']); self::assertEquals('e@mail.com', $response['sendEmailToFriend']['sender']['email']); self::assertEquals('Lorem Ipsum', $response['sendEmailToFriend']['sender']['message']); @@ -117,7 +117,7 @@ public function testSendWithoutExistProduct() $this->expectExceptionMessage( 'The product that was requested doesn\'t exist. Verify the product and try again.' ); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -181,7 +181,7 @@ public function testMaxSendEmailToFriend() QUERY; $this->expectException(\Exception::class); $this->expectExceptionMessage("No more than {$sendFriend->getMaxRecipients()} emails can be sent at a time."); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -214,7 +214,7 @@ public function testErrors(string $input, string $errorMessage) QUERY; $this->expectException(\Exception::class); $this->expectExceptionMessage($errorMessage); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -270,7 +270,7 @@ public function testLimitMessagesPerHour() ); for ($i = 0; $i <= $sendFriend->getMaxSendsToFriend() + 1; $i++) { - $this->graphQlQuery($query); + $this->graphQlMutation($query); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlMutationTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlMutationTest.php index ef1dea1c18f54..35f408b255a84 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlMutationTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlMutationTest.php @@ -28,7 +28,7 @@ public function testMutation() } MUTATION; - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); $this->assertArrayHasKey('testItem', $response); $testItem = $response['testItem']; $this->assertArrayHasKey('integer_list', $testItem); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlQueryTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlQueryTest.php index 690844222929f..fa3af0179d8ff 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlQueryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlQueryTest.php @@ -77,4 +77,26 @@ public function testQueryViaGetRequestReturnsResults() $this->assertArrayHasKey('testItem', $response); } + + public function testQueryViaGetRequestWithVariablesReturnsResults() + { + $id = 1; + + $query = <<<QUERY +{ + testItem(\$id: Int!) + { + item_id + name + } +} +QUERY; + $variables = [ + "id" => $id + ]; + + $response = $this->graphQlQuery($query, $variables, '', [], 'GET'); + + $this->assertArrayHasKey('testItem', $response); + } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index 463f2c4af101f..6861bb8dbb240 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -142,6 +142,6 @@ private function sendRequestWithToken(string $query): array $customerToken = $this->customerTokenService->createCustomerAccessToken('customer@example.com', 'password'); $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; - return $this->graphQlQuery($query, [], '', $headerMap); + return $this->graphQlMutation($query, [], '', $headerMap); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Vault/CustomerPaymentTokensTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Vault/CustomerPaymentTokensTest.php index 89fbbb9c49ed3..97e86b9c6ac96 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Vault/CustomerPaymentTokensTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Vault/CustomerPaymentTokensTest.php @@ -139,7 +139,7 @@ public function testDeletePaymentToken() } } QUERY; - $response = $this->graphQlQuery($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); + $response = $this->graphQlMutation($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); $this->assertTrue($response['deletePaymentToken']['result']); $this->assertEquals(1, count($response['deletePaymentToken']['customerPaymentTokens']['items'])); @@ -168,7 +168,7 @@ public function testDeletePaymentTokenIfUserIsNotAuthorized() } } QUERY; - $this->graphQlQuery($query, [], ''); + $this->graphQlMutation($query, [], ''); } /** @@ -190,7 +190,7 @@ public function testDeletePaymentTokenInvalidPublicHash() } } QUERY; - $this->graphQlQuery($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); + $this->graphQlMutation($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); } /** diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php index 0f7dfa97e8e2e..2beeff64b4831 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php @@ -38,6 +38,9 @@ class GraphQlControllerTest extends \Magento\TestFramework\Indexer\TestCase /** @var MetadataPool */ private $metadataPool; + /** @var Http */ + private $request; + public static function setUpBeforeClass() { $db = Bootstrap::getInstance()->getBootstrap() @@ -57,6 +60,7 @@ protected function setUp() : void $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); $this->metadataPool = $this->objectManager->get(MetadataPool::class); + $this->request = $this->objectManager->get(Http::class); } /** @@ -86,28 +90,27 @@ public function testDispatch() : void } QUERY; $postData = [ - 'query' => $query, - 'variables' => null, + 'query' => $query, + 'variables' => null, 'operationName' => null ]; - /** @var Http $request */ - $request = $this->objectManager->get(Http::class); - $request->setPathInfo('/graphql'); - $request->setMethod('POST'); - $request->setContent(json_encode($postData)); + + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('POST'); + $this->request->setContent(json_encode($postData)); $headers = $this->objectManager->create(\Zend\Http\Headers::class) ->addHeaders(['Content-Type' => 'application/json']); - $request->setHeaders($headers); - $response = $this->graphql->dispatch($request); + $this->request->setHeaders($headers); + $response = $this->graphql->dispatch($this->request); $output = $this->jsonSerializer->unserialize($response->getContent()); $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); $this->assertArrayNotHasKey('errors', $output, 'Response has errors'); - $this->assertTrue(!empty($output['data']['products']['items']), 'Products array has items'); - $this->assertTrue(!empty($output['data']['products']['items'][0]), 'Products array has items'); - $this->assertEquals($output['data']['products']['items'][0]['id'], $product->getData($linkField)); - $this->assertEquals($output['data']['products']['items'][0]['sku'], $product->getSku()); - $this->assertEquals($output['data']['products']['items'][0]['name'], $product->getName()); + $this->assertNotEmpty($output['data']['products']['items'], 'Products array has items'); + $this->assertNotEmpty($output['data']['products']['items'][0], 'Products array has items'); + $this->assertEquals($product->getData($linkField), $output['data']['products']['items'][0]['id']); + $this->assertEquals($product->getSku(), $output['data']['products']['items'][0]['sku']); + $this->assertEquals($product->getName(), $output['data']['products']['items'][0]['name']); } /** @@ -136,21 +139,20 @@ public function testDispatchWithGet() : void } } QUERY; - /** @var Http $request */ - $request = $this->objectManager->get(Http::class); - $request->setPathInfo('/graphql'); - $request->setMethod('GET'); - $request->setQueryValue('query', $query); - $response = $this->graphql->dispatch($request); + + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('GET'); + $this->request->setQueryValue('query', $query); + $response = $this->graphql->dispatch($this->request); $output = $this->jsonSerializer->unserialize($response->getContent()); $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); $this->assertArrayNotHasKey('errors', $output, 'Response has errors'); - $this->assertTrue(!empty($output['data']['products']['items']), 'Products array has items'); - $this->assertTrue(!empty($output['data']['products']['items'][0]), 'Products array has items'); - $this->assertEquals($output['data']['products']['items'][0]['id'], $product->getData($linkField)); - $this->assertEquals($output['data']['products']['items'][0]['sku'], $product->getSku()); - $this->assertEquals($output['data']['products']['items'][0]['name'], $product->getName()); + $this->assertNotEmpty($output['data']['products']['items'], 'Products array has items'); + $this->assertNotEmpty($output['data']['products']['items'][0], 'Products array has items'); + $this->assertEquals($product->getData($linkField), $output['data']['products']['items'][0]['id']); + $this->assertEquals($product->getSku(), $output['data']['products']['items'][0]['sku']); + $this->assertEquals($product->getName(), $output['data']['products']['items'][0]['name']); } /** Test request is dispatched and response generated when using GET request with parameterized query string @@ -177,32 +179,31 @@ public function testDispatchGetWithParameterizedVariables() : void } } QUERY; + $variables = [ - 'filterInput'=>[ - 'sku' =>['eq' => 'simple1'] + 'filterInput' => [ + 'sku' => ['eq' => 'simple1'] ] ]; $queryParams = [ - 'query' => $query, - 'variables' => json_encode($variables), + 'query' => $query, + 'variables' => json_encode($variables), 'operationName' => 'GetProducts' ]; - /** @var Http $request */ - $request = $this->objectManager->get(Http::class); - $request->setPathInfo('/graphql'); - $request->setMethod('GET'); - $request->setParams($queryParams); - $response = $this->graphql->dispatch($request); + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('GET'); + $this->request->setParams($queryParams); + $response = $this->graphql->dispatch($this->request); $output = $this->jsonSerializer->unserialize($response->getContent()); $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); $this->assertArrayNotHasKey('errors', $output, 'Response has errors'); - $this->assertTrue(!empty($output['data']['products']['items']), 'Products array has items'); - $this->assertTrue(!empty($output['data']['products']['items'][0]), 'Products array has items'); - $this->assertEquals($output['data']['products']['items'][0]['id'], $product->getData($linkField)); - $this->assertEquals($output['data']['products']['items'][0]['sku'], $product->getSku()); - $this->assertEquals($output['data']['products']['items'][0]['name'], $product->getName()); + $this->assertNotEmpty($output['data']['products']['items'], 'Products array has items'); + $this->assertNotEmpty($output['data']['products']['items'][0], 'Products array has items'); + $this->assertEquals($product->getData($linkField), $output['data']['products']['items'][0]['id']); + $this->assertEquals($product->getSku(), $output['data']['products']['items'][0]['sku']); + $this->assertEquals($product->getName(), $output['data']['products']['items'][0]['name']); } /** @@ -232,26 +233,25 @@ public function testError() : void QUERY; $postData = [ - 'query' => $query, - 'variables' => null, + 'query' => $query, + 'variables' => null, 'operationName' => null ]; - /** @var Http $request */ - $request = $this->objectManager->get(Http::class); - $request->setPathInfo('/graphql'); - $request->setMethod('POST'); - $request->setContent(json_encode($postData)); + + $this->request->setPathInfo('/graphql'); + $this->request->setMethod('POST'); + $this->request->setContent(json_encode($postData)); $headers = $this->objectManager->create(\Zend\Http\Headers::class) ->addHeaders(['Content-Type' => 'application/json']); - $request->setHeaders($headers); - $response = $this->graphql->dispatch($request); + $this->request->setHeaders($headers); + $response = $this->graphql->dispatch($this->request); $outputResponse = $this->jsonSerializer->unserialize($response->getContent()); if (isset($outputResponse['errors'][0])) { if (is_array($outputResponse['errors'][0])) { foreach ($outputResponse['errors'] as $error) { $this->assertEquals( - $error['category'], - \Magento\Framework\GraphQl\Exception\GraphQlInputException::EXCEPTION_CATEGORY + \Magento\Framework\GraphQl\Exception\GraphQlInputException::EXCEPTION_CATEGORY, + $error['category'] ); if (isset($error['message'])) { $this->assertEquals($error['message'], 'Invalid entity_type specified: invalid'); diff --git a/lib/internal/Magento/Framework/GraphQl/Exception/GraphQlRequestException.php b/lib/internal/Magento/Framework/GraphQl/Exception/GraphQlRequestException.php deleted file mode 100644 index 8fef0a4791081..0000000000000 --- a/lib/internal/Magento/Framework/GraphQl/Exception/GraphQlRequestException.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\Framework\GraphQl\Exception; - -use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Phrase; - -/** - * Exception for GraphQL to be thrown when user supplies invalid input - */ -class GraphQlRequestException extends LocalizedException implements \GraphQL\Error\ClientAware -{ - const EXCEPTION_CATEGORY = 'graphql-request'; - - /** - * @var boolean - */ - private $isSafe; - - /** - * Initialize object - * - * @param Phrase $phrase - * @param \Exception $cause - * @param int $code - * @param boolean $isSafe - */ - public function __construct(Phrase $phrase, \Exception $cause = null, $code = 0, $isSafe = true) - { - $this->isSafe = $isSafe; - parent::__construct($phrase, $cause, $code); - } - - /** - * @inheritdoc - */ - public function isClientSafe() : bool - { - return $this->isSafe; - } - - /** - * @inheritdoc - */ - public function getCategory() : string - { - return self::EXCEPTION_CATEGORY; - } -} From 43fad756dc4ca51fe3a60888b67976772f07cc8a Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Thu, 4 Apr 2019 17:35:43 -0500 Subject: [PATCH 378/603] GraphQL-481: [Test Coverage] 'RemoveCouponFromCart' functionality --- .../testsuite/Magento/Quote/Api/CouponManagementTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CouponManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CouponManagementTest.php index 13ec50139b7fb..1fb8fc43b0db6 100644 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CouponManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CouponManagementTest.php @@ -9,6 +9,9 @@ use Magento\TestFramework\TestCase\WebapiAbstract; +/** + * Coupon management service tests + */ class CouponManagementTest extends WebapiAbstract { const SERVICE_VERSION = 'V1'; From 7cd48fc3b92c67d3d99257e3d302a931acd966a1 Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Fri, 5 Apr 2019 10:30:36 +0530 Subject: [PATCH 379/603] Fixed Changing sample for downloadable product failure --- app/code/Magento/Downloadable/Model/SampleRepository.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Downloadable/Model/SampleRepository.php b/app/code/Magento/Downloadable/Model/SampleRepository.php index 0c7d2b96f1b53..98af48d1df993 100644 --- a/app/code/Magento/Downloadable/Model/SampleRepository.php +++ b/app/code/Magento/Downloadable/Model/SampleRepository.php @@ -308,8 +308,11 @@ protected function updateSample( $existingSample->setTitle($sample->getTitle()); } - if ($sample->getSampleType() === 'file' && $sample->getSampleFileContent() === null) { - $sample->setSampleFile($existingSample->getSampleFile()); + if ($sample->getSampleType() === 'file' + && $sample->getSampleFileContent() === null + && $sample->getSampleFile() !== null + ) { + $existingSample->setSampleFile($sample->getSampleFile()); } $this->saveSample($product, $sample, $isGlobalScopeContent); return $existingSample->getId(); From 0bf820270f4a3f7a1da2a3b4be49a37d533bdf6e Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Fri, 5 Apr 2019 09:50:43 +0300 Subject: [PATCH 380/603] MAGETWO-98603: [2.3] Fixed Tier Pricing for Bundle items doesn't work --- .../Product/View/Type/Bundle/Option.php | 4 +- .../Magento/Bundle/Model/Product/Price.php | 151 +++++++++--------- 2 files changed, 79 insertions(+), 76 deletions(-) diff --git a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle/Option.php b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle/Option.php index 6a60854f80e64..7c5a64ca0232f 100644 --- a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle/Option.php +++ b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle/Option.php @@ -171,7 +171,7 @@ protected function assignSelection(\Magento\Bundle\Model\Option $option, $select { if (is_array($selectionId)) { $this->_selectedOptions = $selectionId; - } else if ($selectionId && $option->getSelectionById($selectionId)) { + } elseif ($selectionId && $option->getSelectionById($selectionId)) { $this->_selectedOptions = $selectionId; } elseif (!$option->getRequired()) { $this->_selectedOptions = 'None'; @@ -301,7 +301,7 @@ public function getSelectionTitlePrice($selection, $includeContainer = true) */ public function setValidationContainer($elementId, $containerId) { - return; + return ''; } /** diff --git a/app/code/Magento/Bundle/Model/Product/Price.php b/app/code/Magento/Bundle/Model/Product/Price.php index c9ed97fada966..0e75ad2dc828c 100644 --- a/app/code/Magento/Bundle/Model/Product/Price.php +++ b/app/code/Magento/Bundle/Model/Product/Price.php @@ -258,67 +258,68 @@ public function getTotalPrices($product, $which = null, $includeTax = null, $tak foreach ($options as $option) { /* @var $option \Magento\Bundle\Model\Option */ $selections = $option->getSelections(); - if ($selections) { - $selectionMinimalPrices = []; - $selectionMaximalPrices = []; - - foreach ($option->getSelections() as $selection) { - /* @var $selection \Magento\Bundle\Model\Selection */ - if (!$selection->isSalable()) { - /** - * @todo CatalogInventory Show out of stock Products - */ - continue; - } - - $qty = $selection->getSelectionQty(); - - $item = $product->getPriceType() == self::PRICE_TYPE_FIXED ? $product : $selection; - - $selectionMinimalPrices[] = $this->_catalogData->getTaxPrice( - $item, - $this->getSelectionFinalTotalPrice( - $product, - $selection, - 1, - $qty, - true, - $takeTierPrice - ), - $includeTax - ); - $selectionMaximalPrices[] = $this->_catalogData->getTaxPrice( - $item, - $this->getSelectionFinalTotalPrice( - $product, - $selection, - 1, - null, - true, - $takeTierPrice - ), - $includeTax + if (empty($selections)) { + continue; + } + $selectionMinimalPrices = []; + $selectionMaximalPrices = []; + + foreach ($option->getSelections() as $selection) { + /* @var $selection \Magento\Bundle\Model\Selection */ + if (!$selection->isSalable()) { + /** + * @todo CatalogInventory Show out of stock Products + */ + continue; + } + + $qty = $selection->getSelectionQty(); + + $item = $product->getPriceType() == self::PRICE_TYPE_FIXED ? $product : $selection; + + $selectionMinimalPrices[] = $this->_catalogData->getTaxPrice( + $item, + $this->getSelectionFinalTotalPrice( + $product, + $selection, + 1, + $qty, + true, + $takeTierPrice + ), + $includeTax + ); + $selectionMaximalPrices[] = $this->_catalogData->getTaxPrice( + $item, + $this->getSelectionFinalTotalPrice( + $product, + $selection, + 1, + null, + true, + $takeTierPrice + ), + $includeTax + ); + } + + if (count($selectionMinimalPrices)) { + $selMinPrice = min($selectionMinimalPrices); + if ($option->getRequired()) { + $minimalPrice += $selMinPrice; + $minPriceFounded = true; + } elseif (true !== $minPriceFounded) { + $selMinPrice += $minimalPrice; + $minPriceFounded = false === $minPriceFounded ? $selMinPrice : min( + $minPriceFounded, + $selMinPrice ); } - if (count($selectionMinimalPrices)) { - $selMinPrice = min($selectionMinimalPrices); - if ($option->getRequired()) { - $minimalPrice += $selMinPrice; - $minPriceFounded = true; - } elseif (true !== $minPriceFounded) { - $selMinPrice += $minimalPrice; - $minPriceFounded = false === $minPriceFounded ? $selMinPrice : min( - $minPriceFounded, - $selMinPrice - ); - } - - if ($option->isMultiSelection()) { - $maximalPrice += array_sum($selectionMaximalPrices); - } else { - $maximalPrice += max($selectionMaximalPrices); - } + if ($option->isMultiSelection()) { + $maximalPrice += array_sum($selectionMaximalPrices); + } else { + $maximalPrice += max($selectionMaximalPrices); } } } @@ -341,23 +342,25 @@ public function getTotalPrices($product, $which = null, $includeTax = null, $tak $prices[] = $valuePrice; } - if (count($prices)) { - if ($customOption->getIsRequire()) { - $minimalPrice += $this->_catalogData->getTaxPrice($product, min($prices), $includeTax); - } - - $multiTypes = [ - \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_CHECKBOX, - \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_MULTIPLE, - ]; - - if (in_array($customOption->getType(), $multiTypes)) { - $maximalValue = array_sum($prices); - } else { - $maximalValue = max($prices); - } - $maximalPrice += $this->_catalogData->getTaxPrice($product, $maximalValue, $includeTax); + if (empty($prices)) { + continue; + } + + if ($customOption->getIsRequire()) { + $minimalPrice += $this->_catalogData->getTaxPrice($product, min($prices), $includeTax); + } + + $multiTypes = [ + \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_CHECKBOX, + \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_MULTIPLE, + ]; + + if (in_array($customOption->getType(), $multiTypes)) { + $maximalValue = array_sum($prices); + } else { + $maximalValue = max($prices); } + $maximalPrice += $this->_catalogData->getTaxPrice($product, $maximalValue, $includeTax); } else { $valuePrice = $customOption->getPrice(true); From 79ae8bb7f6487ee6a8dcfcf335444660c5337d8b Mon Sep 17 00:00:00 2001 From: Lusine Papyan <Lusine_Papyan@epam.com> Date: Fri, 5 Apr 2019 10:28:09 +0400 Subject: [PATCH 381/603] MAGETWO-96429: Wrong special price displayed in product search results - Update automated test script --- .../Test/Mftf/Section/StorefrontQuickSearchResultsSection.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Search/Test/Mftf/Section/StorefrontQuickSearchResultsSection.xml b/app/code/Magento/Search/Test/Mftf/Section/StorefrontQuickSearchResultsSection.xml index 81b025c9554e2..ff9fce57c4524 100644 --- a/app/code/Magento/Search/Test/Mftf/Section/StorefrontQuickSearchResultsSection.xml +++ b/app/code/Magento/Search/Test/Mftf/Section/StorefrontQuickSearchResultsSection.xml @@ -12,6 +12,7 @@ <element name="searchTextBox" type="text" selector="#search"/> <element name="searchTextBoxButton" type="button" selector="button[class='action search']"/> <element name="productLink" type="select" selector="a[class='product-item-link']"/> + <element name="productSpecialPrice" type="text" selector="//a[contains(text(), '{{productName}}')]/ancestor::div//span[contains(@data-price-type, 'finalPrice')]/span[contains(@class, 'price')]" parameterized="true"/> <element name="asLowAsLabel" type="text" selector=".minimal-price-link > span"/> <element name="textArea" type="text" selector="li[class='item']"/> <element name="regularPrice" type="text" selector="//span[@class='price-wrapper ']/span[@class='price']"/> From 2a343dd8e60d7cc9ba8fa037dd8dbd2f51ab6d46 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 5 Apr 2019 13:43:20 +0300 Subject: [PATCH 382/603] Fix static and integration tests. --- app/code/Magento/Sales/Model/Order/Payment.php | 1 + app/code/Magento/Sales/Model/RefundOrder.php | 1 + app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php | 1 + app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php | 1 + .../testsuite/Magento/Sales/Service/V1/RefundOrderTest.php | 1 + .../Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php | 5 +++-- .../Sales/_files/order_with_invoice_and_custom_status.php | 1 + .../_files/order_with_invoice_and_custom_status_rollback.php | 1 + 8 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Model/Order/Payment.php b/app/code/Magento/Sales/Model/Order/Payment.php index dcf6d86b44cae..5d1d3f0d040a7 100644 --- a/app/code/Magento/Sales/Model/Order/Payment.php +++ b/app/code/Magento/Sales/Model/Order/Payment.php @@ -684,6 +684,7 @@ public function refund($creditmemo) $gateway->refund($this, $baseAmountToRefund); $creditmemo->setTransactionId($this->getLastTransId()); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (\Magento\Framework\Exception\LocalizedException $e) { if (!$captureTxn) { throw new \Magento\Framework\Exception\LocalizedException( diff --git a/app/code/Magento/Sales/Model/RefundOrder.php b/app/code/Magento/Sales/Model/RefundOrder.php index 97daab0615736..07555cba1b7f7 100644 --- a/app/code/Magento/Sales/Model/RefundOrder.php +++ b/app/code/Magento/Sales/Model/RefundOrder.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model; use Magento\Framework\App\ResourceConnection; diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php index 7798fdd2ce285..9d0f10a30e6ef 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Model\Order; use Magento\Framework\Model\Context; diff --git a/app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php b/app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php index 5962b11311e7d..1ffeaa053cc2e 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Model; use Magento\Framework\App\ResourceConnection; diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php index 37fa36f707ad4..92942d7acc6f2 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Service\V1; use Magento\Sales\Model\Order; diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php index 0a85fe5fbd380..f589a0f5a1c74 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php @@ -10,15 +10,16 @@ use Magento\Framework\App\Request\Http as HttpRequest; use Magento\Sales\Api\Data\OrderItemInterface; use Magento\Sales\Model\Order; -use Magento\TestFramework\TestCase\AbstractBackendController; use PHPUnit\Framework\Constraint\StringContains; /** * Provide tests for CreditMemo save controller. * + * @magentoDbIsolation enabled * @magentoAppArea adminhtml + * @magentoDataFixture Magento/Sales/_files/invoice.php */ -class SaveTest extends AbstractBackendController +class SaveTest extends AbstractCreditmemoControllerTest { /** * @var string diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status.php index 0ee9e95a56b49..46d3fb547cd09 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status.php @@ -8,6 +8,7 @@ use Magento\Sales\Model\Order\Status; use Magento\TestFramework\Helper\Bootstrap; +// phpcs:ignore Magento2.Security.IncludeFile require 'invoice.php'; $orderStatus = Bootstrap::getObjectManager()->create(Status::class); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status_rollback.php index af31c7b4f24a4..274cb3c74395d 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_invoice_and_custom_status_rollback.php @@ -8,6 +8,7 @@ use Magento\Sales\Model\Order\Status; use Magento\TestFramework\Helper\Bootstrap; +// phpcs:ignore Magento2.Security.IncludeFile require 'default_rollback.php'; /** @var Status $orderStatus */ From b4c615882068d9c32b65fef112835a195122c852 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 5 Apr 2019 14:40:39 +0300 Subject: [PATCH 383/603] Fix static and unit tests. --- .../Frontend/Quote/Address/CollectTotalsObserver.php | 5 +++++ .../Frontend/Quote/Address/CollectTotalsObserverTest.php | 5 +---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Quote/Observer/Frontend/Quote/Address/CollectTotalsObserver.php b/app/code/Magento/Quote/Observer/Frontend/Quote/Address/CollectTotalsObserver.php index b5e3f4ae1887b..77dfec9603a5c 100644 --- a/app/code/Magento/Quote/Observer/Frontend/Quote/Address/CollectTotalsObserver.php +++ b/app/code/Magento/Quote/Observer/Frontend/Quote/Address/CollectTotalsObserver.php @@ -7,6 +7,11 @@ use Magento\Framework\Event\ObserverInterface; +/** + * Handle customer VAT number on collect_totals_before event of quote address. + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) + */ class CollectTotalsObserver implements ObserverInterface { /** diff --git a/app/code/Magento/Quote/Test/Unit/Observer/Frontend/Quote/Address/CollectTotalsObserverTest.php b/app/code/Magento/Quote/Test/Unit/Observer/Frontend/Quote/Address/CollectTotalsObserverTest.php index f3357f8aacd31..4ea067c9be8f6 100644 --- a/app/code/Magento/Quote/Test/Unit/Observer/Frontend/Quote/Address/CollectTotalsObserverTest.php +++ b/app/code/Magento/Quote/Test/Unit/Observer/Frontend/Quote/Address/CollectTotalsObserverTest.php @@ -199,7 +199,7 @@ public function testDispatchWithCustomerCountryNotInEUAndNotLoggedCustomerInGrou ->method('getNotLoggedInGroup') ->will($this->returnValue($this->groupInterfaceMock)); $this->groupInterfaceMock->expects($this->once()) - ->method('getId')->will($this->returnValue(0)); + ->method('getId')->will($this->returnValue(null)); $this->vatValidatorMock->expects($this->once()) ->method('isEnabled') ->with($this->quoteAddressMock, $this->storeId) @@ -220,9 +220,6 @@ public function testDispatchWithCustomerCountryNotInEUAndNotLoggedCustomerInGrou $this->returnValue(false) ); - $groupMock = $this->getMockBuilder(\Magento\Customer\Api\Data\GroupInterface::class) - ->disableOriginalConstructor() - ->getMock(); $this->customerMock->expects($this->once())->method('getId')->will($this->returnValue(null)); /** Assertions */ From 63a497e04c95a9e18df75c0f7f846758d346555e Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Fri, 5 Apr 2019 14:52:16 +0300 Subject: [PATCH 384/603] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Fixed api-functional tests; --- .../testsuite/Magento/Ups/_files/enable_ups_shipping_method.php | 1 + .../Magento/Ups/_files/enable_ups_shipping_method_rollback.php | 1 + 2 files changed, 2 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method.php b/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method.php index 5c6c60866fafb..09e6c265a9d05 100644 --- a/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method.php +++ b/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method.php @@ -15,6 +15,7 @@ $configWriter = $objectManager->get(WriterInterface::class); $configWriter->save('carriers/ups/active', 1); +$configWriter->save('carriers/ups/type', "UPS"); $scopeConfig = $objectManager->get(ScopeConfigInterface::class); $scopeConfig->clean(); diff --git a/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method_rollback.php b/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method_rollback.php index 6d7894879f97b..e4226d2d1e457 100644 --- a/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method_rollback.php @@ -14,3 +14,4 @@ $configWriter = $objectManager->create(WriterInterface::class); $configWriter->delete('carriers/ups/active'); +$configWriter->delete('carriers/ups/type'); From 191fc7ce4d52c5fbc515204156c708a6de97535e Mon Sep 17 00:00:00 2001 From: Antoine Daudenthun <adaudenthun@gmail.com> Date: Fri, 5 Apr 2019 10:16:29 +0200 Subject: [PATCH 385/603] unregister phar only when appropriate Calling stream_wrapper_unregister('phar') without checking if it's registered will trigger a warning --- app/bootstrap.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/bootstrap.php b/app/bootstrap.php index ddbcaffd42962..4974acdf0fc80 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -8,7 +8,9 @@ * Environment initialization */ error_reporting(E_ALL); -stream_wrapper_unregister('phar'); +if (in_array('phar', \stream_get_wrappers())) { + stream_wrapper_unregister('phar'); +} #ini_set('display_errors', 1); /* PHP version validation */ From 5ac9d3b0f7b20bec5cbebeb67fd4af3a5baca092 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 5 Apr 2019 08:19:17 -0500 Subject: [PATCH 386/603] 229: [GraphQL caching] Add support for queries via HTTP GET - Fix static tests --- .../Magento/TestFramework/TestCase/GraphQl/Client.php | 3 +++ .../Magento/GraphQl/Customer/UpdateCustomerTest.php | 7 ++++++- .../Magento/GraphQl/TestModule/GraphQlMutationTest.php | 2 +- .../Magento/GraphQl/Vault/CustomerPaymentTokensTest.php | 7 ++++++- .../Magento/GraphQl/Controller/GraphQlControllerTest.php | 8 -------- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php index 5eea3be840ae5..1b27d000adb3c 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php @@ -101,12 +101,14 @@ private function processResponse(string $response) $responseArray = $this->json->jsonDecode($response); if (!is_array($responseArray)) { + //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Unknown GraphQL response body: ' . $response); } $this->processErrors($responseArray); if (!isset($responseArray['data'])) { + //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Unknown GraphQL response body: ' . $response); } @@ -142,6 +144,7 @@ private function processErrors($responseBodyArray) $responseBodyArray ); } + //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('GraphQL responded with an unknown error: ' . json_encode($responseBodyArray)); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php index 53c20ad898505..d4f8053826bcf 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php @@ -87,7 +87,12 @@ public function testUpdateCustomer() } } QUERY; - $response = $this->graphQlMutation($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); + $response = $this->graphQlMutation( + $query, + [], + '', + $this->getCustomerAuthHeaders($currentEmail, $currentPassword) + ); $this->assertEquals($newPrefix, $response['updateCustomer']['customer']['prefix']); $this->assertEquals($newFirstname, $response['updateCustomer']['customer']['firstname']); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlMutationTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlMutationTest.php index 35f408b255a84..c85f63c083700 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlMutationTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlMutationTest.php @@ -53,6 +53,6 @@ public function testMutationIsNotAllowedViaGetRequest() } MUTATION; - $this->graphQlQuery($query, [], '', [], 'GET'); + $this->graphQlQuery($query, [], '', []); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Vault/CustomerPaymentTokensTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Vault/CustomerPaymentTokensTest.php index 97e86b9c6ac96..b2d89828f211f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Vault/CustomerPaymentTokensTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Vault/CustomerPaymentTokensTest.php @@ -139,7 +139,12 @@ public function testDeletePaymentToken() } } QUERY; - $response = $this->graphQlMutation($query, [], '', $this->getCustomerAuthHeaders($currentEmail, $currentPassword)); + $response = $this->graphQlMutation( + $query, + [], + '', + $this->getCustomerAuthHeaders($currentEmail, $currentPassword) + ); $this->assertTrue($response['deletePaymentToken']['result']); $this->assertEquals(1, count($response['deletePaymentToken']['customerPaymentTokens']['items'])); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php index 2beeff64b4831..d0d746812ec44 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php @@ -265,12 +265,4 @@ public function testError() : void } } } - - /** - * teardown - */ - public function tearDown() - { - parent::tearDown(); - } } From 656f2b0e0dd8891e0ebc5796514f3547fbd43df9 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 5 Apr 2019 08:47:39 -0500 Subject: [PATCH 387/603] 229: [GraphQL caching] Add support for queries via HTTP GET - fix web-api tests --- .../Magento/TestFramework/TestCase/GraphQl/Client.php | 5 +++-- .../GraphQl/Framework/QueryComplexityLimiterTest.php | 3 ++- .../Magento/GraphQl/TestModule/GraphQlQueryTest.php | 7 ++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php index 1b27d000adb3c..e18a8c8e97c79 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/GraphQl/Client.php @@ -81,9 +81,10 @@ public function get(string $query, array $variables = [], string $operationName $url = $this->getEndpointUrl(); $requestArray = [ 'query' => $query, - 'variables' => empty($variables) ? $variables : null, - 'operationName' => empty($operationName) ? $operationName : null + 'variables' => $variables ? $this->json->jsonEncode($variables) : null, + 'operationName' => $operationName ?? null ]; + array_filter($requestArray); $responseBody = $this->curlClient->get($url, $requestArray, $headers); return $this->processResponse($responseBody); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Framework/QueryComplexityLimiterTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Framework/QueryComplexityLimiterTest.php index 352947714360a..e784061d5562f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Framework/QueryComplexityLimiterTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Framework/QueryComplexityLimiterTest.php @@ -393,7 +393,8 @@ public function testQueryComplexityIsLimited() QUERY; self::expectExceptionMessageRegExp('/Max query complexity should be 300 but got 302/'); - $this->graphQlQuery($query); + //Use POST request because request uri is too large for some servers + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlQueryTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlQueryTest.php index fa3af0179d8ff..2db06e383758f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlQueryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/TestModule/GraphQlQueryTest.php @@ -73,7 +73,7 @@ public function testQueryViaGetRequestReturnsResults() } QUERY; - $response = $this->graphQlQuery($query, [], '', [], 'GET'); + $response = $this->graphQlQuery($query, [], '', []); $this->assertArrayHasKey('testItem', $response); } @@ -83,8 +83,9 @@ public function testQueryViaGetRequestWithVariablesReturnsResults() $id = 1; $query = <<<QUERY +query getTestItem(\$id: Int!) { - testItem(\$id: Int!) + testItem(id: \$id) { item_id name @@ -95,7 +96,7 @@ public function testQueryViaGetRequestWithVariablesReturnsResults() "id" => $id ]; - $response = $this->graphQlQuery($query, $variables, '', [], 'GET'); + $response = $this->graphQlQuery($query, $variables, '', []); $this->assertArrayHasKey('testItem', $response); } From d3a9199774293c9cdee86210f7b20f5102333e99 Mon Sep 17 00:00:00 2001 From: Veronika Kurochkina <veronika_kurochkina@epam.com> Date: Fri, 5 Apr 2019 17:04:14 +0300 Subject: [PATCH 388/603] MAGETWO-58764: [GitHub] Minimal Query Length For Catalog Search #6681 --- .../Model/Search/Adapter/Mysql/Query/Builder/Match.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php b/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php index b8640f67811f7..4490cf031e5e1 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php +++ b/app/code/Magento/CatalogGraphQl/Model/Search/Adapter/Mysql/Query/Builder/Match.php @@ -24,11 +24,6 @@ class Match extends BuilderMatch */ private $searchHelper; - /** - * @var string[] - */ - private $replaceSymbols = []; - /** * @param ResolverInterface $resolver * @param Fulltext $fulltextHelper @@ -52,8 +47,8 @@ public function __construct( */ protected function prepareQuery($queryValue, $conditionType) { - $this->replaceSymbols = str_split(self::SPECIAL_CHARACTERS, 1); - $queryValue = str_replace($this->replaceSymbols, ' ', $queryValue); + $replaceSymbols = str_split(self::SPECIAL_CHARACTERS, 1); + $queryValue = str_replace($replaceSymbols, ' ', $queryValue); foreach ($this->preprocessors as $preprocessor) { $queryValue = $preprocessor->process($queryValue); } From f875c6d37670eaea0ce68634f6df246907ce6a45 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 5 Apr 2019 10:37:27 -0500 Subject: [PATCH 389/603] Add migrated tag to MTF test --- .../Captcha/Test/TestCase/CaptchaOnStoreFrontLoginTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnStoreFrontLoginTest.xml b/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnStoreFrontLoginTest.xml index 8e4327db5eddc..8068b2cbc050e 100644 --- a/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnStoreFrontLoginTest.xml +++ b/dev/tests/functional/tests/app/Magento/Captcha/Test/TestCase/CaptchaOnStoreFrontLoginTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Captcha\Test\TestCase\CaptchaOnStoreFrontLoginTest" summary="Check CAPTCHA on StoreFront Login Page" ticketId="MAGETWO-43639"> <variation name="CaptchaOnStoreFrontLoginTestVariation1"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="customer/dataset" xsi:type="string">default</data> <data name="captcha" xsi:type="string">111</data> <data name="configData" xsi:type="string">captcha_storefront_login</data> From 29a039df5851c8e5f62b927a6b4312d9e774fe9e Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Fri, 5 Apr 2019 12:40:55 -0500 Subject: [PATCH 390/603] GraphQL-481: [Test Coverage] 'RemoveCouponFromCart' functionality --- .../GraphQl/Quote/Customer/RemoveCouponFromCartTest.php | 8 ++++---- .../GraphQl/Quote/Guest/RemoveCouponFromCartTest.php | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveCouponFromCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveCouponFromCartTest.php index 689b360f724a7..feba8c5c64259 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveCouponFromCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveCouponFromCartTest.php @@ -39,7 +39,7 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent_generalusers.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php @@ -85,7 +85,7 @@ public function testRemoveCouponFromEmptyCart() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -103,7 +103,7 @@ public function testRemoveCouponFromCartIfCouponWasNotSet() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php @@ -120,7 +120,7 @@ public function testRemoveCouponFromGuestCart() /** * @magentoApiDataFixture Magento/Customer/_files/three_customers.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent_generalusers.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveCouponFromCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveCouponFromCartTest.php index a17ef545eba88..edb5f9cbf267c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveCouponFromCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveCouponFromCartTest.php @@ -31,7 +31,7 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php @@ -74,7 +74,7 @@ public function testRemoveCouponFromEmptyCart() } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ @@ -92,7 +92,7 @@ public function testRemoveCouponFromCartIfCouponWasNotSet() /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent_generalusers.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php From ddc90cfbf1c978d5aea65560ddf3532762bc0e47 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 5 Apr 2019 14:04:48 -0500 Subject: [PATCH 391/603] Test stabilization --- .../Captcha/Test/Mftf/Test/AdminLoginWithCaptchaTest.xml | 2 ++ .../Customer/Test/Mftf/Test/StorefrontForgotPasswordTest.xml | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/AdminLoginWithCaptchaTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/AdminLoginWithCaptchaTest.xml index 6c3bf9b127b1e..e5ee55910df65 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Test/AdminLoginWithCaptchaTest.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Test/AdminLoginWithCaptchaTest.xml @@ -23,10 +23,12 @@ <before> <magentoCLI command="config:set {{AdminCaptchaLength3ConfigData.path}} {{AdminCaptchaLength3ConfigData.value}}" stepKey="setCaptchaLength" /> <magentoCLI command="config:set {{AdminCaptchaSymbols1ConfigData.path}} {{AdminCaptchaSymbols1ConfigData.value}}" stepKey="setCaptchaSymbols" /> + <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> </before> <after> <magentoCLI command="config:set {{AdminCaptchaDefaultLengthConfigData.path}} {{AdminCaptchaDefaultLengthConfigData.value}}" stepKey="setDefaultCaptchaLength" /> <magentoCLI command="config:set {{AdminCaptchaDefaultSymbolsConfigData.path}} {{AdminCaptchaDefaultSymbolsConfigData.value}}" stepKey="setDefaultCaptchaSymbols" /> + <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdminWithWrongCredentialsFirstAttempt"> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontForgotPasswordTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontForgotPasswordTest.xml index 12e603bd3748c..8d4be5fda3c79 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontForgotPasswordTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontForgotPasswordTest.xml @@ -20,10 +20,11 @@ <group value="mtf_migrated"/> </annotations> <before> - <magentoCLI command="config:set customer/captcha/enable 0" stepKey="disableCaptcha"/> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaDisableConfigData.path}} {{StorefrontCustomerCaptchaDisableConfigData.value}}" stepKey="disableCaptcha"/> <createData stepKey="customer" entity="Simple_US_Customer"/> </before> <after> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaEnableConfigData.path}} {{StorefrontCustomerCaptchaEnableConfigData.value}}" stepKey="enableCaptcha"/> <deleteData stepKey="deleteCustomer" createDataKey="customer" /> </after> From fef452adae8dde46c395afbe02ba6a7b2d88bcc7 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Fri, 5 Apr 2019 15:05:30 -0500 Subject: [PATCH 392/603] MC-15440: Product Page Gallery Load Optimization --- .../Catalog/Block/Product/View/Gallery.php | 23 ++----------------- app/code/Magento/Catalog/Helper/Image.php | 3 ++- .../frontend/layout/catalog_product_view.xml | 6 ++++- .../templates/product/view/gallery.phtml | 20 +++++++++++++++- 4 files changed, 28 insertions(+), 24 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Product/View/Gallery.php b/app/code/Magento/Catalog/Block/Product/View/Gallery.php index fb2898544d804..8b98fbdc8f7ef 100644 --- a/app/code/Magento/Catalog/Block/Product/View/Gallery.php +++ b/app/code/Magento/Catalog/Block/Product/View/Gallery.php @@ -207,8 +207,8 @@ public function isMainImage($image) */ public function getImageAttribute($imageId, $attributeName, $default = null) { - $attributes = - $this->getConfigView()->getMediaAttributes('Magento_Catalog', Image::MEDIA_TYPE_CONFIG_NODE, $imageId); + $attributes = $this->getConfigView() + ->getMediaAttributes('Magento_Catalog', Image::MEDIA_TYPE_CONFIG_NODE, $imageId); return $attributes[$attributeName] ?? $default; } @@ -239,23 +239,4 @@ private function getGalleryImagesConfig() return $this->getData('gallery_images_config'); } - - /** - * Get main product image - * - * @param string $size - * @return string - */ - public function getMainProductImage($size = 'medium_image_url') - { - foreach ($this->getGalleryImages() as $image) { - $image = $image->getData($size); - - if (!$image) { - return $this->_imageHelper->getDefaultPlaceholderUrl('image'); - } - - return $image; - } - } } diff --git a/app/code/Magento/Catalog/Helper/Image.php b/app/code/Magento/Catalog/Helper/Image.php index 170f1209ad9e6..cc2a1cd7cb481 100644 --- a/app/code/Magento/Catalog/Helper/Image.php +++ b/app/code/Magento/Catalog/Helper/Image.php @@ -6,6 +6,7 @@ namespace Magento\Catalog\Helper; use Magento\Framework\App\Helper\AbstractHelper; +use Magento\Framework\View\Element\Block\ArgumentInterface; /** * Catalog image helper @@ -14,7 +15,7 @@ * @SuppressWarnings(PHPMD.TooManyFields) * @since 100.0.2 */ -class Image extends AbstractHelper +class Image extends AbstractHelper implements ArgumentInterface { /** * Media config node diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml index 8d3248896b434..e987d09728bdb 100644 --- a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml +++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml @@ -121,7 +121,11 @@ </arguments> </block> </container> - <block class="Magento\Catalog\Block\Product\View\Gallery" name="product.info.media.image" template="Magento_Catalog::product/view/gallery.phtml"/> + <block class="Magento\Catalog\Block\Product\View\Gallery" name="product.info.media.image" template="Magento_Catalog::product/view/gallery.phtml"> + <arguments> + <argument name="imageHelper" xsi:type="object">Magento\Catalog\Helper\Image</argument> + </arguments> + </block> <container name="skip_gallery_after.wrapper" htmlTag="div" htmlClass="action-skip-wrapper"> <block class="Magento\Framework\View\Element\Template" after="product.info.media.image" name="skip_gallery_after" template="Magento_Theme::html/skip.phtml"> <arguments> diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml index 820e6cc969175..096761c0a5d5c 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml @@ -13,10 +13,28 @@ */ ?> +<?php + $images = $block->getGalleryImages()->getItems(); + $mainImage = current(array_filter($images, function ($img) use ($block) { + return $block->isMainImage($img); + })); + + if (!empty($images) && empty($mainImage)) { + $mainImage = $block->getGalleryImages()->getFirstItem(); + } + + $helper = $block->getData('imageHelper'); + $mainImageData = $mainImage ? + $mainImage->getData('medium_image_url') : + $helper->getDefaultPlaceholderUrl('image'); + +?> + <div class="gallery-placeholder _block-content-loading" data-gallery-role="gallery-placeholder"> <img + alt="main product photo" class="gallery-placeholder__image" - src="<?= /* @escapeNotVerified */ $block->getMainProductImage() ?>" + src="<?= /* @noEscape */ $mainImageData ?>" /> </div> From 04e576be255c99dd209043268acef4429df26193 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 5 Apr 2019 15:11:11 -0500 Subject: [PATCH 393/603] Test stabilization --- .../Test/Mftf/Test/AdminAdvancedReportingButtonTest.xml | 3 +++ .../AssertCaptchaVisibleOnCustomerAccountInfoActionGroup.xml | 2 ++ 2 files changed, 5 insertions(+) diff --git a/app/code/Magento/Analytics/Test/Mftf/Test/AdminAdvancedReportingButtonTest.xml b/app/code/Magento/Analytics/Test/Mftf/Test/AdminAdvancedReportingButtonTest.xml index 505e178f49f43..e660a2eb8d428 100644 --- a/app/code/Magento/Analytics/Test/Mftf/Test/AdminAdvancedReportingButtonTest.xml +++ b/app/code/Magento/Analytics/Test/Mftf/Test/AdminAdvancedReportingButtonTest.xml @@ -13,6 +13,9 @@ <title value="AdvancedReportingButtonTest"/> <description value="Test log in to AdvancedReporting and tests AdvancedReportingButtonTest"/> <testCaseId value="MC-14800"/> + <skip> + <issueId value="MC-14800" /> + </skip> <severity value="CRITICAL"/> <group value="analytics"/> <group value="mtf_migrated"/> diff --git a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerAccountInfoActionGroup.xml b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerAccountInfoActionGroup.xml index ef28705cc7a26..c68ffbfb5be4b 100644 --- a/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerAccountInfoActionGroup.xml +++ b/app/code/Magento/Captcha/Test/Mftf/ActionGroup/AssertCaptchaVisibleOnCustomerAccountInfoActionGroup.xml @@ -9,11 +9,13 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertCaptchaVisibleOnCustomerAccountInfoActionGroup"> + <checkOption selector="{{StorefrontCustomerAccountInformationSection.changeEmail}}" stepKey="clickChangeEmailCheckbox" /> <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaField}}" stepKey="seeCaptchaField"/> <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaImg}}" stepKey="seeCaptchaImage"/> <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaReload}}" stepKey="seeCaptchaReloadButton"/> <reloadPage stepKey="refreshPage"/> <waitForPageLoad stepKey="waitForPageReloaded" /> + <checkOption selector="{{StorefrontCustomerAccountInformationSection.changeEmail}}" stepKey="clickChangeEmailCheckboxAfterPageReload" /> <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaField}}" stepKey="seeCaptchaFieldAfterPageReload"/> <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaImg}}" stepKey="seeCaptchaImageAfterPageReload"/> <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaReload}}" stepKey="seeCaptchaReloadButtonAfterPageReload"/> From c819cc0e816e7d0710ac379828bd3107dbe176f1 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@adobe.com> Date: Fri, 5 Apr 2019 15:58:48 -0500 Subject: [PATCH 394/603] Strict comparison with null instead of is_null function usage --- .../ConfigurableProduct/Model/Product/Type/Configurable.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php index 47c1a3c39f9a8..a849d964eaed5 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php @@ -1249,7 +1249,7 @@ public function getUsedProducts($product, $requiredAttributeIds = null) $product->getStoreId(), $this->getCustomerSession()->getCustomerGroupId() ]; - if (!is_null($requiredAttributeIds)) { + if ($requiredAttributeIds !== null) { sort($requiredAttributeIds); $keyParts[] = implode('', $requiredAttributeIds); } From 3cefd3a172075c68bc552d4187cdcff0ec307ee4 Mon Sep 17 00:00:00 2001 From: Ji Lu <jilu1@adobe.com> Date: Fri, 5 Apr 2019 16:31:31 -0500 Subject: [PATCH 395/603] MQE-1509: Updated annotation in mftf test AdminUpdateCategoryUrlRewriteAndAddTemporaryRedirectTest --- ...AdminUpdateCategoryUrlRewriteAndAddTemporaryRedirectTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddTemporaryRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddTemporaryRedirectTest.xml index 7453b7b5a43f3..7e1b9acbc47ab 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddTemporaryRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddTemporaryRedirectTest.xml @@ -10,7 +10,7 @@ <test name="AdminUpdateCategoryUrlRewriteAndAddTemporaryRedirectTest"> <annotations> <stories value="Update URL rewrite"/> - <title value="Update Category URL Rewrites, no redirect type"/> + <title value="Update Category URL Rewrites, Temporary redirect type"/> <description value="Login as Admin and update category UrlRewrite and add Temporary redirect type"/> <testCaseId value="MC-5356"/> <severity value="CRITICAL"/> From 2ab7760b616d06a817b9f960878cde78af185a69 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 5 Apr 2019 17:10:39 -0500 Subject: [PATCH 396/603] Minor fixes to magento/magento-functional-tests-migration#682 --- ...refrontResetCustomerPasswordFailedTest.xml | 19 ++++++++++++++++ ...AssertCustomerResetPasswordActionGroup.xml | 22 +++++++++++++++++++ ...efrontCustomerResetPasswordActionGroup.xml | 12 ---------- ...refrontResetCustomerPasswordFailedTest.xml | 4 ++-- .../ResetCustomerPasswordFailedTest.xml | 3 +-- 5 files changed, 44 insertions(+), 16 deletions(-) create mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerResetPasswordActionGroup.xml diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml new file mode 100644 index 0000000000000..36d7989b9acc1 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml @@ -0,0 +1,19 @@ +<?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="StorefrontResetCustomerPasswordFailedTest"> + <before> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaDisableConfigData.path}} {{StorefrontCustomerCaptchaDisableConfigData.value}}" stepKey="disableCaptcha"/> + </before> + <after> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaEnableConfigData.path}} {{StorefrontCustomerCaptchaEnableConfigData.value}}" stepKey="enableCaptcha"/> + </after> + </test> +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerResetPasswordActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerResetPasswordActionGroup.xml new file mode 100644 index 0000000000000..644254443d129 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerResetPasswordActionGroup.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="AssertCustomerResetPasswordActionGroup"> + <arguments> + <argument name="url" type="string"/> + <argument name="message" type="string" defaultValue="" /> + <argument name="messageType" type="string" defaultValue="success" /> + </arguments> + + <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.messageByType(messageType)}}" stepKey="waitForMessage" /> + <see stepKey="seeMessage" userInput="{{message}}" selector="{{StorefrontCustomerLoginMessagesSection.messageByType(messageType)}}"/> + <seeInCurrentUrl stepKey="seeCorrectCurrentUrl" url="{{url}}"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerResetPasswordActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerResetPasswordActionGroup.xml index f322be6109218..a28593f1b77b7 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerResetPasswordActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerResetPasswordActionGroup.xml @@ -21,16 +21,4 @@ <click stepKey="clickResetPassword" selector="{{StorefrontForgotPasswordSection.resetMyPasswordButton}}"/> <waitForPageLoad stepKey="waitForPageLoaded" /> </actionGroup> - - <actionGroup name="AssertCustomerResetPasswordActionGroup"> - <arguments> - <argument name="url" type="string"/> - <argument name="message" type="string" defaultValue="" /> - <argument name="messageType" type="string" defaultValue="success" /> - </arguments> - - <seeInCurrentUrl stepKey="seeInSignInPage" url="{{url}}"/> - <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.messageByType(messageType)}}" stepKey="waitForMessage" /> - <see stepKey="seeMessage" userInput="{{message}}" selector="{{StorefrontCustomerLoginMessagesSection.messageByType(messageType)}}"/> - </actionGroup> </actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml index 56c8af118fadc..3121bd0da9d2d 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml @@ -13,16 +13,16 @@ <features value="Customer"/> <title value="Customer tries to reset password several times"/> <description value="Customer tries to reset password several times"/> + <severity value="CRITICAL" /> + <testCaseId value="MC-14374" /> <group value="Customer"/> <group value="security"/> <group value="mtf_migrated"/> </annotations> <before> - <magentoCLI command="config:set customer/captcha/enable 0" stepKey="disableCaptcha"/> <createData stepKey="customer" entity="Simple_US_Customer"/> </before> <after> - <magentoCLI command="config:set customer/captcha/enable 1" stepKey="enableCaptcha"/> <deleteData stepKey="deleteCustomer" createDataKey="customer" /> </after> diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetCustomerPasswordFailedTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetCustomerPasswordFailedTest.xml index 524f57c78b4ba..b4fbe7bb92929 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetCustomerPasswordFailedTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetCustomerPasswordFailedTest.xml @@ -8,8 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Security\Test\TestCase\ResetCustomerPasswordFailedTest" summary="Reset customer password."> <variation name="ResetPasswordTestVariation"> - <data name="tag" xsi:type="string">mftf_migrated:yes</data> - <data name="tag" xsi:type="string">severity:S1</data> + <data name="tag" xsi:type="string">severity:S1,mftf_migrated:yes</data> <data name="customer/dataset" xsi:type="string">customer_US</data> <data name="attempts" xsi:type="string">2</data> <data name="configData" xsi:type="string">captcha_storefront_disable</data> From 3ad6bb9c3569f6ce2509c99a293188d1c78ce2a2 Mon Sep 17 00:00:00 2001 From: Pieter Hoste <hoste.pieter@gmail.com> Date: Sat, 6 Apr 2019 11:16:24 +0200 Subject: [PATCH 397/603] Removing incorrect less selector '.abs-cleafix', it has a typo + it is already used correctly in a different less file (_data-grid-header.less). --- .../adminhtml/Magento/backend/web/css/source/forms/_temp.less | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_temp.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_temp.less index 5d9bf80ce2255..71f57b765ff0e 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/_temp.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/_temp.less @@ -470,8 +470,6 @@ label.mage-error { } .admin__data-grid-header-row { - &:extend(.abs-cleafix); - .action-select-multiselect { -webkit-appearance: menulist-button; appearance: menulist-button; From 34bd8bd793de2aad34c461aad62a1a3984fb509a Mon Sep 17 00:00:00 2001 From: Andreas Mautz <andreas.mautz@webvisum.de> Date: Sun, 7 Apr 2019 13:58:40 +0200 Subject: [PATCH 398/603] 22166: updated README to follow-up the switch from Bugcrowd to hackerone --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e3cf448f99fb..01e6df12cb5f5 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Please review the [Code Contributions guide](https://devdocs.magento.com/guides/ ## Reporting Security Issues -To report security vulnerabilities in Magento software or web sites, please create a Bugcrowd researcher account [there](https://bugcrowd.com/magento) to submit and follow-up your issue. Learn more about reporting security issues [here](https://magento.com/security/reporting-magento-security-issue). +To report security vulnerabilities or learn more about reporting security issues in Magento software or web sites visit the [Magento Bug Bounty Program](https://hackerone.com/magento) on hackerone. Please create a hackerone account [there](https://hackerone.com/magento) to submit and follow-up your issue. Stay up-to-date on the latest security news and patches for Magento by signing up for [Security Alert Notifications](https://magento.com/security/sign-up). From 2131a21f183dfd0019c36f90bb4921948552d045 Mon Sep 17 00:00:00 2001 From: Dmytro Cheshun <mitry@atwix.com> Date: Sun, 7 Apr 2019 23:00:20 +0300 Subject: [PATCH 399/603] Add API functional tests for ApplyCouponToCart functionality, code refactoring --- .../Quote/Customer/ApplyCouponToCartTest.php | 284 +++++------------- .../Quote/Guest/ApplyCouponToCartTest.php | 199 +++--------- .../Quote/_files/make_coupon_expired.php | 22 ++ .../_files/make_coupon_expired_rollback.php | 23 ++ ...strict_coupon_usage_for_simple_product.php | 52 ++++ ...upon_usage_for_simple_product_rollback.php | 37 +++ 6 files changed, 252 insertions(+), 365 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/make_coupon_expired.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/make_coupon_expired_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/restrict_coupon_usage_for_simple_product.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/restrict_coupon_usage_for_simple_product_rollback.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php index 2db2e799f9123..885e8705dc3d9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php @@ -8,15 +8,8 @@ namespace Magento\GraphQl\Quote\Customer; use Magento\Framework\Exception\AuthenticationException; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\Integration\Api\CustomerTokenServiceInterface; -use Magento\Quote\Model\Quote; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; -use Magento\SalesRule\Api\Data\ConditionInterface; -use Magento\SalesRule\Api\Data\ConditionInterfaceFactory; -use Magento\SalesRule\Api\RuleRepositoryInterface; -use Magento\SalesRule\Model\Coupon; -use Magento\SalesRule\Model\Spi\CouponResourceInterface; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -25,279 +18,187 @@ */ class ApplyCouponToCartTest extends GraphQlAbstract { - /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var Quote - */ - private $quote; - - /** - * @var QuoteIdToMaskedQuoteIdInterface - */ - private $quoteIdToMaskedId; - - /** - * @var CouponResourceInterface - */ - protected $couponResource; - - /** - * @var Coupon - */ - private $coupon; - /** * @var CustomerTokenServiceInterface */ private $customerTokenService; /** - * @var RuleRepositoryInterface - */ - private $ruleRepository; - - /** - * @var ConditionInterfaceFactory + * @var GetMaskedQuoteIdByReservedOrderId */ - private $conditionFactory; + private $getMaskedQuoteIdByReservedOrderId; protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->create(QuoteResource::class); - $this->quote = $objectManager->create(Quote::class); - $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); - $this->couponResource = $objectManager->get(CouponResourceInterface::class); - $this->coupon = $objectManager->create(Coupon::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); - $this->ruleRepository = $objectManager->get(RuleRepositoryInterface::class); - $this->conditionFactory = $objectManager->get(ConditionInterfaceFactory::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); } /** + * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent_generalusers.php * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ public function testApplyCouponToCart() { $couponCode = '2?ds5!2d'; - - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $response = $this->graphQlQuery($query, [], '', $queryHeaders); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('applyCouponToCart', $response); self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); } /** + * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent_generalusers.php * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @expectedException \Exception * @expectedExceptionMessage A coupon is already applied to the cart. Please remove it to apply another */ public function testApplyCouponTwice() { $couponCode = '2?ds5!2d'; - - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $response = $this->graphQlQuery($query, [], '', $queryHeaders); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey("applyCouponToCart", $response); self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); - $this->graphQlQuery($query, [], '', $queryHeaders); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } /** + * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent_generalusers.php * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @expectedException \Exception * @expectedExceptionMessage Cart does not contain products. */ public function testApplyCouponToCartWithoutItems() { $couponCode = '2?ds5!2d'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); - $this->quoteResource->load($this->quote, 'test_order_1', 'reserved_order_id'); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - - $this->graphQlQuery($query, [], '', $queryHeaders); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php - * @magentoApiDataFixture Magento/Customer/_files/customer.php * @expectedException \Exception */ public function testApplyCouponToGuestCart() { $couponCode = '2?ds5!2d'; - - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query, [], '', $queryHeaders); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } /** + * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent_generalusers.php * @magentoApiDataFixture Magento/Customer/_files/two_customers.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @expectedException \Exception */ public function testApplyCouponToAnotherCustomerCart() { $couponCode = '2?ds5!2d'; - - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $this->quote->setCustomerId(2); - $this->quoteResource->save($this->quote); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query, [], '', $queryHeaders); + $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer_two@example.com')); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @expectedException \Exception * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. */ public function testApplyNonExistentCouponToCart() { - $couponCode = '1%q#f5'; - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $couponCode = 'non_existent_coupon_code'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query, [], '', $queryHeaders); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php * @expectedException \Exception */ public function testApplyCouponToNonExistentCart() { $couponCode = '2?ds5!2d'; - $maskedQuoteId = '1hk3y1842h1n'; - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId, $couponCode); self::expectExceptionMessage('Could not find a cart with ID "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query, [], '', $queryHeaders); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } /** + * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent_generalusers.php * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/make_coupon_expired.php * @expectedException \Exception * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. */ public function testApplyExpiredCoupon() { $couponCode = '2?ds5!2d'; - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); - $this->coupon->loadByCode($couponCode); - $yesterday = new \DateTime(); - $yesterday->add(\DateInterval::createFromDateString('-1 day')); - $this->coupon->setExpirationDate($yesterday->format('Y-m-d')); - $this->couponResource->save($this->coupon); - - $this->graphQlQuery($query, [], '', $queryHeaders); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } /** * Products in cart don't fit to the coupon * + * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent_generalusers.php * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/restrict_coupon_usage_for_simple_product.php * @expectedException \Exception * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. */ public function testApplyCouponWhichIsNotApplicable() { $couponCode = '2?ds5!2d'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $this->excludeProductPerCoupon($couponCode, 'simple'); - - $this->graphQlQuery($query, [], '', $queryHeaders); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } /** @@ -305,6 +206,7 @@ public function testApplyCouponWhichIsNotApplicable() * @param string $message * @dataProvider dataProviderUpdateWithMissedRequiredParameters * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @expectedException \Exception */ public function testApplyCouponWithMissedRequiredParameters(string $input, string $message) @@ -321,12 +223,8 @@ public function testApplyCouponWithMissedRequiredParameters(string $input, strin } QUERY; - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); - $this->expectExceptionMessage($message); - $this->graphQlQuery($query, [], '', $queryHeaders); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } /** @@ -346,55 +244,19 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ]; } - /** - * @param string $couponCode - * @param string $sku - * @throws \Exception - */ - private function excludeProductPerCoupon(string $couponCode, string $sku) - { - $this->coupon->loadByCode($couponCode); - $ruleId = $this->coupon->getRuleId(); - $salesRule = $this->ruleRepository->getById($ruleId); - - /** @var ConditionInterface $conditionProductSku */ - $conditionProductSku = $this->conditionFactory->create(); - $conditionProductSku->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Product::class); - $conditionProductSku->setAttributeName('sku'); - $conditionProductSku->setValue('1'); - $conditionProductSku->setOperator('!='); - $conditionProductSku->setValue($sku); - - /** @var ConditionInterface $conditionProductFound */ - $conditionProductFound = $this->conditionFactory->create(); - $conditionProductFound->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Product\Found::class); - $conditionProductFound->setValue('1'); - $conditionProductFound->setAggregatorType('all'); - $conditionProductFound->setConditions([$conditionProductSku]); - - /** @var ConditionInterface $conditionCombine */ - $conditionCombine = $this->conditionFactory->create(); - $conditionCombine->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Combine::class); - $conditionCombine->setValue('1'); - $conditionCombine->setAggregatorType('all'); - $conditionCombine->setConditions([$conditionProductFound]); - - $salesRule->setCondition($conditionCombine); - $this->ruleRepository->save($salesRule); - } - /** * Retrieve customer authorization headers * - * @param string $email + * @param string $username * @param string $password * @return array * @throws AuthenticationException */ - private function prepareAuthorizationHeaders(string $email, string $password): array + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array { - $customerToken = $this->customerTokenService->createCustomerAccessToken($email, $password); - return ['Authorization' => 'Bearer ' . $customerToken]; + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; } /** @@ -402,7 +264,7 @@ private function prepareAuthorizationHeaders(string $email, string $password): a * @param string $couponCode * @return string */ - private function prepareAddCouponRequestQuery(string $maskedQuoteId, string $couponCode): string + private function getQuery(string $maskedQuoteId, string $couponCode): string { return <<<QUERY mutation { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php index 51644a9fe8c55..4fd1c713db5d4 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php @@ -7,14 +7,7 @@ namespace Magento\GraphQl\Quote\Guest; -use Magento\Quote\Model\Quote; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; -use Magento\SalesRule\Api\Data\ConditionInterface; -use Magento\SalesRule\Api\Data\ConditionInterfaceFactory; -use Magento\SalesRule\Api\RuleRepositoryInterface; -use Magento\SalesRule\Model\Coupon; -use Magento\SalesRule\Model\Spi\CouponResourceInterface; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -24,67 +17,27 @@ class ApplyCouponToCartTest extends GraphQlAbstract { /** - * @var QuoteResource + * @var GetMaskedQuoteIdByReservedOrderId */ - private $quoteResource; - - /** - * @var Quote - */ - private $quote; - - /** - * @var QuoteIdToMaskedQuoteIdInterface - */ - private $quoteIdToMaskedId; - - /** - * @var CouponResourceInterface - */ - protected $couponResource; - - /** - * @var Coupon - */ - private $coupon; - - /** - * @var RuleRepositoryInterface - */ - private $ruleRepository; - - /** - * @var ConditionInterfaceFactory - */ - private $conditionFactory; + private $getMaskedQuoteIdByReservedOrderId; protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->create(QuoteResource::class); - $this->quote = $objectManager->create(Quote::class); - $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); - $this->couponResource = $objectManager->get(CouponResourceInterface::class); - $this->coupon = $objectManager->create(Coupon::class); - $this->ruleRepository = $objectManager->get(RuleRepositoryInterface::class); - $this->conditionFactory = $objectManager->get(ConditionInterfaceFactory::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php */ public function testApplyCouponToCart() { $couponCode = '2?ds5!2d'; - - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); $response = $this->graphQlQuery($query); self::assertArrayHasKey('applyCouponToCart', $response); @@ -92,7 +45,9 @@ public function testApplyCouponToCart() } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php * @expectedException \Exception * @expectedExceptionMessage A coupon is already applied to the cart. Please remove it to apply another @@ -100,14 +55,8 @@ public function testApplyCouponToCart() public function testApplyCouponTwice() { $couponCode = '2?ds5!2d'; - - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); $response = $this->graphQlQuery($query); self::assertArrayHasKey("applyCouponToCart", $response); @@ -117,7 +66,8 @@ public function testApplyCouponTwice() } /** - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php * @expectedException \Exception * @expectedExceptionMessage Cart does not contain products. @@ -125,53 +75,41 @@ public function testApplyCouponTwice() public function testApplyCouponToCartWithoutItems() { $couponCode = '2?ds5!2d'; - - $this->quoteResource->load($this->quote, 'test_order_1', 'reserved_order_id'); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); $this->graphQlQuery($query); } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * _security * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @expectedException \Exception */ public function testApplyCouponToCustomerCart() { $couponCode = '2?ds5!2d'; - - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); $this->graphQlQuery($query); } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @expectedException \Exception * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. */ public function testApplyNonExistentCouponToCart() { - $couponCode = '1%q#f5'; - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $couponCode = 'non_existent_coupon_code'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); $this->graphQlQuery($query); } @@ -183,35 +121,27 @@ public function testApplyNonExistentCouponToCart() public function testApplyCouponToNonExistentCart() { $couponCode = '2?ds5!2d'; - $maskedQuoteId = '1hk3y1842h1n'; - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId, $couponCode); self::expectExceptionMessage('Could not find a cart with ID "' . $maskedQuoteId . '"'); $this->graphQlQuery($query); } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/make_coupon_expired.php * @expectedException \Exception * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. */ public function testApplyExpiredCoupon() { $couponCode = '2?ds5!2d'; - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $this->coupon->loadByCode($couponCode); - - $yesterday = new \DateTime(); - $yesterday->add(\DateInterval::createFromDateString('-1 day')); - $this->coupon->setExpirationDate($yesterday->format('Y-m-d')); - $this->couponResource->save($this->coupon); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); $this->graphQlQuery($query); } @@ -219,23 +149,19 @@ public function testApplyExpiredCoupon() /** * Products in cart don't fit to the coupon * - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/restrict_coupon_usage_for_simple_product.php * @expectedException \Exception * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. */ public function testApplyCouponWhichIsNotApplicable() { $couponCode = '2?ds5!2d'; - - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $this->excludeProductPerCoupon($couponCode, 'simple'); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $couponCode); $this->graphQlQuery($query); } @@ -243,6 +169,8 @@ public function testApplyCouponWhichIsNotApplicable() /** * @param string $input * @param string $message + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @dataProvider dataProviderUpdateWithMissedRequiredParameters * @expectedException \Exception */ @@ -281,49 +209,12 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ]; } - /** - * @param string $couponCode - * @param string $sku - * @throws \Exception - */ - private function excludeProductPerCoupon(string $couponCode, string $sku) - { - $this->coupon->loadByCode($couponCode); - $ruleId = $this->coupon->getRuleId(); - $salesRule = $this->ruleRepository->getById($ruleId); - - /** @var ConditionInterface $conditionProductSku */ - $conditionProductSku = $this->conditionFactory->create(); - $conditionProductSku->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Product::class); - $conditionProductSku->setAttributeName('sku'); - $conditionProductSku->setValue('1'); - $conditionProductSku->setOperator('!='); - $conditionProductSku->setValue($sku); - - /** @var ConditionInterface $conditionProductFound */ - $conditionProductFound = $this->conditionFactory->create(); - $conditionProductFound->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Product\Found::class); - $conditionProductFound->setValue('1'); - $conditionProductFound->setAggregatorType('all'); - $conditionProductFound->setConditions([$conditionProductSku]); - - /** @var ConditionInterface $conditionCombine */ - $conditionCombine = $this->conditionFactory->create(); - $conditionCombine->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Combine::class); - $conditionCombine->setValue('1'); - $conditionCombine->setAggregatorType('all'); - $conditionCombine->setConditions([$conditionProductFound]); - - $salesRule->setCondition($conditionCombine); - $this->ruleRepository->save($salesRule); - } - /** * @param string $maskedQuoteId * @param string $couponCode * @return string */ - private function prepareAddCouponRequestQuery(string $maskedQuoteId, string $couponCode): string + private function getQuery(string $maskedQuoteId, string $couponCode): string { return <<<QUERY mutation { diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/make_coupon_expired.php b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/make_coupon_expired.php new file mode 100644 index 0000000000000..5316b184ecd15 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/make_coupon_expired.php @@ -0,0 +1,22 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\SalesRule\Model\CouponFactory; +use Magento\SalesRule\Model\Spi\CouponResourceInterface; +use Magento\TestFramework\Helper\Bootstrap; + +/** @var CouponResourceInterface $couponResource */ +$couponResource = Bootstrap::getObjectManager()->get(CouponResourceInterface::class); +/** @var CouponFactory $couponFactory */ +$couponFactory = Bootstrap::getObjectManager()->get(CouponFactory::class); + +$coupon = $couponFactory->create(); +$coupon->loadByCode('2?ds5!2d'); +$yesterday = new \DateTime(); +$yesterday->add(\DateInterval::createFromDateString('-1 day')); +$coupon->setExpirationDate($yesterday->format('Y-m-d')); +$couponResource->save($coupon); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/make_coupon_expired_rollback.php b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/make_coupon_expired_rollback.php new file mode 100644 index 0000000000000..32c3d78bafd09 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/make_coupon_expired_rollback.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\SalesRule\Model\CouponFactory; +use Magento\SalesRule\Model\Spi\CouponResourceInterface; +use Magento\TestFramework\Helper\Bootstrap; + +/** @var CouponResourceInterface $couponResource */ +$couponResource = Bootstrap::getObjectManager()->get(CouponResourceInterface::class); +/** @var CouponFactory $couponFactory */ +$couponFactory = Bootstrap::getObjectManager()->get(CouponFactory::class); + +$coupon = $couponFactory->create(); +$coupon->loadByCode('2?ds5!2d'); + +if ($coupon->getId()) { + $coupon->setExpirationDate(null); + $couponResource->save($coupon); +} diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/restrict_coupon_usage_for_simple_product.php b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/restrict_coupon_usage_for_simple_product.php new file mode 100644 index 0000000000000..e58c6b21d8d23 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/restrict_coupon_usage_for_simple_product.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\SalesRule\Api\Data\ConditionInterface; +use Magento\SalesRule\Api\Data\ConditionInterfaceFactory; +use Magento\SalesRule\Api\RuleRepositoryInterface; +use Magento\SalesRule\Model\CouponFactory; +use Magento\TestFramework\Helper\Bootstrap; + +/** @var CouponFactory $couponFactory */ +$couponFactory = Bootstrap::getObjectManager()->get(CouponFactory::class); +/** @var ConditionInterfaceFactory $conditionFactory */ +$conditionFactory = Bootstrap::getObjectManager()->get(ConditionInterfaceFactory::class); +/** @var RuleRepositoryInterface $ruleRepository */ +$ruleRepository = Bootstrap::getObjectManager()->get(RuleRepositoryInterface::class); + +$couponCode = '2?ds5!2d'; +$sku = 'simple_product'; + +$coupon = $couponFactory->create(); +$coupon->loadByCode($couponCode); +$ruleId = $coupon->getRuleId(); +$salesRule = $ruleRepository->getById($ruleId); + +/** @var ConditionInterface $conditionProductSku */ +$conditionProductSku = $conditionFactory->create(); +$conditionProductSku->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Product::class); +$conditionProductSku->setAttributeName('sku'); +$conditionProductSku->setValue('1'); +$conditionProductSku->setOperator('!='); +$conditionProductSku->setValue($sku); + +/** @var ConditionInterface $conditionProductFound */ +$conditionProductFound = $conditionFactory->create(); +$conditionProductFound->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Product\Found::class); +$conditionProductFound->setValue('1'); +$conditionProductFound->setAggregatorType('all'); +$conditionProductFound->setConditions([$conditionProductSku]); + +/** @var ConditionInterface $conditionCombine */ +$conditionCombine = $conditionFactory->create(); +$conditionCombine->setConditionType(\Magento\SalesRule\Model\Rule\Condition\Combine::class); +$conditionCombine->setValue('1'); +$conditionCombine->setAggregatorType('all'); +$conditionCombine->setConditions([$conditionProductFound]); + +$salesRule->setCondition($conditionCombine); +$ruleRepository->save($salesRule); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/restrict_coupon_usage_for_simple_product_rollback.php b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/restrict_coupon_usage_for_simple_product_rollback.php new file mode 100644 index 0000000000000..86ab253f1d3c0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/restrict_coupon_usage_for_simple_product_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\SalesRule\Api\Data\ConditionInterface; +use Magento\SalesRule\Api\Data\ConditionInterfaceFactory; +use Magento\SalesRule\Api\RuleRepositoryInterface; +use Magento\SalesRule\Model\CouponFactory; +use Magento\TestFramework\Helper\Bootstrap; + +/** @var CouponFactory $couponFactory */ +$couponFactory = Bootstrap::getObjectManager()->get(CouponFactory::class); +/** @var ConditionInterfaceFactory $conditionFactory */ +$conditionFactory = Bootstrap::getObjectManager()->get(ConditionInterfaceFactory::class); +/** @var RuleRepositoryInterface $ruleRepository */ +$ruleRepository = Bootstrap::getObjectManager()->get(RuleRepositoryInterface::class); + +$couponCode = '2?ds5!2d'; +$sku = 'simple_product'; + +$coupon = $couponFactory->create(); +$coupon->loadByCode($couponCode); + +if ($coupon->getId()) { + $ruleId = $coupon->getRuleId(); + $salesRule = $ruleRepository->getById($ruleId); + + /** @var ConditionInterface $conditionCombine */ + $conditionCombine = $conditionFactory->create(); + $conditionCombine->setConditions([]); + + $salesRule->setCondition($conditionCombine); + $ruleRepository->save($salesRule); +} From 9675984b0487996de1521e2ba70d35ad7f77a788 Mon Sep 17 00:00:00 2001 From: WEXO team <support@wexo.dk> Date: Mon, 8 Apr 2019 10:40:30 +0600 Subject: [PATCH 400/603] fatalErrorHandler returns 500 only on fatal errors fatalogErrorHandler should return 500 only on fatal errors - otherwise, even a simple deprecation warning on the page triggers internal server error, which is invalid. --- pub/health_check.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pub/health_check.php b/pub/health_check.php index c9a4965876bb7..06c79baa2fd81 100644 --- a/pub/health_check.php +++ b/pub/health_check.php @@ -70,7 +70,7 @@ function fatalErrorHandler() { $error = error_get_last(); - if ($error !== null) { + if ($error !== null && $error['type'] === E_ERROR) { http_response_code(500); } } From 594badbb07888ed4156493a0c4354c71c3100365 Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Mon, 8 Apr 2019 10:23:47 +0530 Subject: [PATCH 401/603] Fixed wrong url redirect when edit product review from product view page --- app/code/Magento/Review/Block/Adminhtml/Edit/Form.php | 3 ++- app/code/Magento/Review/Controller/Adminhtml/Product/Save.php | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php b/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php index 8a8395de72b62..8ca6d695113b9 100644 --- a/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php +++ b/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php @@ -84,7 +84,8 @@ protected function _prepareForm() 'review/*/save', [ 'id' => $this->getRequest()->getParam('id'), - 'ret' => $this->_coreRegistry->registry('ret') + 'ret' => $this->_coreRegistry->registry('ret'), + 'productId' => $this->getRequest()->getParam('productId') ] ), 'method' => 'post', diff --git a/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php b/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php index 6217729f53e50..9c85ae7db22d9 100644 --- a/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php +++ b/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php @@ -73,6 +73,10 @@ public function execute() } else { $resultRedirect->setPath('*/*/'); } + $productId = $this->getRequest()->getParam('productId'); + if ($productId) { + $resultRedirect->setPath("catalog/product/edit/id/$productId"); + } return $resultRedirect; } $resultRedirect->setPath('review/*/'); From 8256077236f6999df755b7fb71cb1ccbd53f2174 Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Mon, 8 Apr 2019 10:58:12 +0530 Subject: [PATCH 402/603] Correct spelling --- .../adminhtml/Magento/backend/web/css/source/forms/_fields.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less index 5698afdaac7ae..66c9086c15aa7 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less @@ -81,7 +81,7 @@ min-width: 0; padding: 0; - // Filedset section + // Fieldset section .fieldset-wrapper { &.admin__fieldset-section { > .fieldset-wrapper-title { From 09b35a252f282283100a721ead25b9634e412f6e Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Mon, 8 Apr 2019 11:02:11 +0530 Subject: [PATCH 403/603] Correct spelling --- .../Magento/Catalog/Model/Product/Gallery/CreateHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php index 42b9639d2717b..d6416a024c6df 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php @@ -206,7 +206,7 @@ public function execute($product, $arguments = []) } /** - * Returns media gallery atribute instance + * Returns media gallery attribute instance * * @return \Magento\Catalog\Api\Data\ProductAttributeInterface * @since 101.0.0 From 639e97b7cbc287c6e435ab1cc8d0ae7cb82d4076 Mon Sep 17 00:00:00 2001 From: Yogesh Suhagiya <yksuhagiya@gmail.com> Date: Mon, 8 Apr 2019 11:35:52 +0530 Subject: [PATCH 404/603] Translated exception message --- app/code/Magento/Braintree/Controller/Paypal/PlaceOrder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Braintree/Controller/Paypal/PlaceOrder.php b/app/code/Magento/Braintree/Controller/Paypal/PlaceOrder.php index 418cb93900610..ea8a44a1122b4 100644 --- a/app/code/Magento/Braintree/Controller/Paypal/PlaceOrder.php +++ b/app/code/Magento/Braintree/Controller/Paypal/PlaceOrder.php @@ -75,7 +75,7 @@ public function execute() $this->logger->critical($e); $this->messageManager->addExceptionMessage( $e, - 'The order #' . $quote->getReservedOrderId() . ' cannot be processed.' + __('The order #%1 cannot be processed.', $quote->getReservedOrderId()) ); } From fd5d25455f4213d0dffbdfb76aa3ded264db3c2f Mon Sep 17 00:00:00 2001 From: Yogesh Suhagiya <yksuhagiya@gmail.com> Date: Mon, 8 Apr 2019 12:10:01 +0530 Subject: [PATCH 405/603] Translate comment in DHL config settings --- app/code/Magento/Dhl/etc/adminhtml/system.xml | 2 +- app/code/Magento/Dhl/i18n/en_US.csv | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Dhl/etc/adminhtml/system.xml b/app/code/Magento/Dhl/etc/adminhtml/system.xml index 37b653225c7b9..7ab37de2f3658 100644 --- a/app/code/Magento/Dhl/etc/adminhtml/system.xml +++ b/app/code/Magento/Dhl/etc/adminhtml/system.xml @@ -31,7 +31,7 @@ <field id="account" translate="label" type="text" sortOrder="70" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> <label>Account Number</label> </field> - <field id="content_type" translate="label" type="select" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> + <field id="content_type" translate="label comment" type="select" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> <label>Content Type (Non Domestic)</label> <comment>Whether to use Documents or NonDocuments service for non domestic shipments. (Shipments within the EU are classed as domestic)</comment> <source_model>Magento\Dhl\Model\Source\Contenttype</source_model> diff --git a/app/code/Magento/Dhl/i18n/en_US.csv b/app/code/Magento/Dhl/i18n/en_US.csv index a5532c2cea963..0e4c7a8385b93 100644 --- a/app/code/Magento/Dhl/i18n/en_US.csv +++ b/app/code/Magento/Dhl/i18n/en_US.csv @@ -61,6 +61,7 @@ Title,Title Password,Password "Account Number","Account Number" "Content Type","Content Type" +"Whether to use Documents or NonDocuments service for non domestic shipments. (Shipments within the EU are classed as domestic)","Whether to use Documents or NonDocuments service for non domestic shipments. (Shipments within the EU are classed as domestic)" "Calculate Handling Fee","Calculate Handling Fee" "Handling Applied","Handling Applied" """Per Order"" allows a single handling fee for the entire order. ""Per Package"" allows an individual handling fee for each package.","""Per Order"" allows a single handling fee for the entire order. ""Per Package"" allows an individual handling fee for each package." From 4e6e1a15ccb773f2ce023e6a01ed6c46f6e30360 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Mon, 8 Apr 2019 09:40:21 +0300 Subject: [PATCH 406/603] MC-13339: Adding new options with images and prices to Configurable Product --- .../Cms/Test/Mftf/Data/CmsPageData.xml | 2 + .../AdminConfigurableProductActionGroup.xml | 10 ++ ...reateApiConfigurableProductActionGroup.xml | 2 +- .../StorefrontProductActionGroup.xml | 14 +- .../AdminProductFormConfigurationsSection.xml | 2 + ...agesAndPricesToConfigurableProductTest.xml | 124 ++++++++++++++++++ 6 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml diff --git a/app/code/Magento/Cms/Test/Mftf/Data/CmsPageData.xml b/app/code/Magento/Cms/Test/Mftf/Data/CmsPageData.xml index 2ec2eccba2344..2f8efac37cecf 100644 --- a/app/code/Magento/Cms/Test/Mftf/Data/CmsPageData.xml +++ b/app/code/Magento/Cms/Test/Mftf/Data/CmsPageData.xml @@ -50,6 +50,7 @@ <data key="file_type">Upload File</data> <data key="shareable">Yes</data> <data key="file">magento-again.jpg</data> + <data key="fileName">magento-again</data> <data key="value">magento-again.jpg</data> <data key="content">Image content. Yeah.</data> <data key="height">1000</data> @@ -71,6 +72,7 @@ <data key="file_type">Upload File</data> <data key="shareable">Yes</data> <data key="value">magento3.jpg</data> + <data key="file">magento3.jpg</data> <data key="fileName">magento3</data> <data key="extension">jpg</data> <data key="content">Image content. Yeah.</data> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml index 43dae2d70d416..069838231d775 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminConfigurableProductActionGroup.xml @@ -276,4 +276,14 @@ <seeInField userInput="{{ApiConfigurableProduct.sku}}" selector="{{AdminProductFormSection.productSku}}" stepKey="seeSkuRequired"/> <dontSeeInField userInput="{{ApiConfigurableProduct.price}}" selector="{{AdminProductFormSection.productPrice}}" stepKey="dontSeePriceRequired"/> </actionGroup> + + <!--Click in Next Step and see Title--> + <actionGroup name="AdminConfigurableWizardMoveToNextStepActionGroup"> + <arguments> + <argument name="title" type="string"/> + </arguments> + <click selector="{{ConfigurableProductSection.nextButton}}" stepKey="clickNextButton"/> + <waitForPageLoad stepKey="waitForNextStepLoaded"/> + <see userInput="{{title}}" selector="{{AdminProductFormConfigurationsSection.stepsWizardTitle}}" stepKey="seeStepTitle"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateApiConfigurableProductActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateApiConfigurableProductActionGroup.xml index c0a9f03906030..5feaab40a7695 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateApiConfigurableProductActionGroup.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateApiConfigurableProductActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminCreateApiConfigurableProductActionGroup"> <arguments> - <argument name="productName" defaultValue="ApiConfigurableProductWithOutCategory" type="string"/> + <argument name="productName" defaultValue="{{ApiConfigurableProductWithOutCategory.name}}" type="string"/> </arguments> <!-- Create the configurable product based on the data in the /data folder --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontProductActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontProductActionGroup.xml index 51bb041b66089..d7f85dc9e08a2 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontProductActionGroup.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/StorefrontProductActionGroup.xml @@ -66,6 +66,18 @@ <seeElement selector="{{StorefrontProductMediaSection.imageFile(image.filename)}}" stepKey="seeFirstImage"/> </actionGroup> + <!-- Assert option image and price in storefront product page --> + <actionGroup name="AssertOptionImageAndPriceInStorefrontProductActionGroup"> + <arguments> + <argument name="label" type="string"/> + <argument name="image" type="string"/> + <argument name="price" type="string"/> + </arguments> + <selectOption userInput="{{label}}" selector="{{StorefrontProductInfoMainSection.productAttributeOptionsSelectButton}}" stepKey="selectOption"/> + <seeElement selector="{{StorefrontProductMediaSection.imageFile(image)}}" stepKey="seeImage"/> + <see userInput="{{price}}" selector="{{StorefrontProductInfoMainSection.price}}" stepKey="seeProductPrice"/> + </actionGroup> + <!-- Assert configurable product with special price in storefront product page --> <actionGroup name="assertConfigurableProductWithSpecialPriceOnStorefrontProductPage"> <arguments> @@ -78,4 +90,4 @@ <see userInput="Regular Price" selector="{{StorefrontProductInfoMainSection.specialProductText}}" stepKey="seeText"/> <see userInput="{{price}}" selector="{{StorefrontProductInfoMainSection.oldProductPrice}}" stepKey="seeOldProductPrice"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml index d1b16cb8f5ce3..f6828a3b86312 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml @@ -36,6 +36,8 @@ <element name="variationsSkuInputByRow" selector="[data-index='configurable-matrix'] table > tbody > tr:nth-of-type({{row}}) input[name*='sku']" type="input" parameterized="true"/> <element name="variationsSkuInputErrorByRow" selector="[data-index='configurable-matrix'] table > tbody > tr:nth-of-type({{row}}) .admin__field-error" type="text" parameterized="true"/> <element name="variationLabel" type="text" selector="//div[@data-index='configurable-matrix']/label"/> + <element name="stepsWizardTitle" type="text" selector="div.content:not([style='display: none;']) .steps-wizard-title"/> + <element name="attributeEntityByName" type="text" selector="//div[@class='attribute-entity']//div[normalize-space(.)='{{attributeLabel}}']" parameterized="true"/> </section> <section name="AdminConfigurableProductFormSection"> <element name="productWeight" type="input" selector=".admin__control-text[name='product[weight]']"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml new file mode 100644 index 0000000000000..52443a17dfe64 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml @@ -0,0 +1,124 @@ +<?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="AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest"> + <annotations> + <features value="ConfigurableProduct"/> + <stories value="Update product"/> + <title value="Adding new options with images and prices to Configurable Product"/> + <description value="Test case verifies possibility to add new options for configurable attribute for existing configurable product."/> + <severity value="CRITICAL"/> + <testCaseId value="MC-13339"/> + <group value="configurableProduct"/> + </annotations> + + <before> + <actionGroup ref="AdminCreateApiConfigurableProductActionGroup" stepKey="createConfigurableProduct"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + + <after> + <deleteData createDataKey="createConfigProductCreateConfigurableProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="createConfigProductAttributeCreateConfigurableProduct" stepKey="deleteConfigProductAttribute"/> + <deleteData createDataKey="createConfigChildProduct1CreateConfigurableProduct" stepKey="deleteConfigChildProduct1"/> + <deleteData createDataKey="createConfigChildProduct2CreateConfigurableProduct" stepKey="deleteConfigChildProduct2"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Open edit product page--> + <amOnPage url="{{AdminProductEditPage.url($$createConfigProductCreateConfigurableProduct.id$$)}}" stepKey="goToProductEditPage"/> + + <!--Open edit configuration wizard--> + <click selector="{{AdminProductFormConfigurationsSection.createConfigurations}}" stepKey="clickEditConfigurations"/> + <see userInput="Select Attributes" selector="{{AdminProductFormConfigurationsSection.stepsWizardTitle}}" stepKey="seeStepTitle"/> + + <!--Click Next button--> + <actionGroup ref="AdminConfigurableWizardMoveToNextStepActionGroup" stepKey="navigateToAttributeValuesStep"> + <argument name="title" value="Attribute Values"/> + </actionGroup> + <seeElement selector="{{AdminProductFormConfigurationsSection.attributeEntityByName($$createConfigProductAttributeCreateConfigurableProduct.default_frontend_label$$)}}" stepKey="seeAttribute"/> + + <!--Create one color option via "Create New Value" link--> + <click selector="{{AdminCreateProductConfigurationsPanel.createNewValue}}" stepKey="clickOnCreateNewValue"/> + <fillField userInput="{{colorDefaultProductAttribute1.name}}" selector="{{AdminCreateProductConfigurationsPanel.attributeName}}" stepKey="fillFieldForNewAttribute"/> + <click selector="{{AdminCreateProductConfigurationsPanel.saveAttribute}}" stepKey="clickOnSaveNewAttribute"/> + + <!--Click Next button--> + <actionGroup ref="AdminConfigurableWizardMoveToNextStepActionGroup" stepKey="navigateToBulkStep"> + <argument name="title" value="Bulk Images, Price and Quantity"/> + </actionGroup> + + <!--Select Apply unique images by attribute to each SKU and color attribute in dropdown in Images--> + <click selector="{{AdminCreateProductConfigurationsPanel.applyUniqueImagesToEachSkus}}" stepKey="clickOnApplyUniqueImagesToEachSku"/> + <selectOption userInput="$$createConfigProductAttributeCreateConfigurableProduct.default_frontend_label$$" + selector="{{AdminCreateProductConfigurationsPanel.selectImagesButton}}" stepKey="selectAttributeOption"/> + + <!-- Add images to configurable product attribute options --> + <actionGroup ref="addUniqueImageToConfigurableProductOption" stepKey="addImageToConfigurableProductOptionOne"> + <argument name="image" value="ImageUpload"/> + <argument name="frontend_label" value="$$createConfigProductAttributeCreateConfigurableProduct.default_frontend_label$$"/> + <argument name="label" value="$$getConfigAttributeOption1CreateConfigurableProduct.label$$"/> + </actionGroup> + <actionGroup ref="addUniqueImageToConfigurableProductOption" stepKey="addImageToConfigurableProductOptionTwo"> + <argument name="image" value="ImageUpload_1"/> + <argument name="frontend_label" value="$$createConfigProductAttributeCreateConfigurableProduct.default_frontend_label$$"/> + <argument name="label" value="$$getConfigAttributeOption2CreateConfigurableProduct.label$$"/> + </actionGroup> + <actionGroup ref="addUniqueImageToConfigurableProductOption" stepKey="addImageToConfigurableProductOptionThree"> + <argument name="image" value="ImageUpload3"/> + <argument name="frontend_label" value="$$createConfigProductAttributeCreateConfigurableProduct.default_frontend_label$$"/> + <argument name="label" value="{{colorDefaultProductAttribute1.name}}"/> + </actionGroup> + + <!--Add prices to configurable product attribute options--> + <click selector="{{AdminCreateProductConfigurationsPanel.applyUniquePricesToEachSkus}}" stepKey="clickOnApplyUniquePricesByAttributeToEachSku"/> + <selectOption userInput="$$createConfigProductAttributeCreateConfigurableProduct.default_frontend_label$$" + selector="{{AdminCreateProductConfigurationsPanel.selectAttribute}}" stepKey="selectAttributes"/> + <fillField userInput="10" selector="{{AdminCreateProductConfigurationsPanel.price($$getConfigAttributeOption1CreateConfigurableProduct.label$$)}}" stepKey="fillAttributePrice"/> + <fillField userInput="20" selector="{{AdminCreateProductConfigurationsPanel.price($$getConfigAttributeOption2CreateConfigurableProduct.label$$)}}" stepKey="fillAttributePrice1"/> + <fillField userInput="30" selector="{{AdminCreateProductConfigurationsPanel.price(colorDefaultProductAttribute1.name)}}" stepKey="fillAttributePrice2"/> + + <!-- Add quantity to product attribute options --> + <click selector="{{AdminCreateProductConfigurationsPanel.applySingleQuantityToEachSkus}}" stepKey="clickOnApplySingleQuantityToEachSku"/> + <fillField selector="{{AdminCreateProductConfigurationsPanel.quantity}}" userInput="100" stepKey="enterAttributeQuantity"/> + + <!--Click Next button--> + <actionGroup ref="AdminConfigurableWizardMoveToNextStepActionGroup" stepKey="navigateToSummaryStep"> + <argument name="title" value="Summary"/> + </actionGroup> + + <!--Click Generate Configure button--> + <click selector="{{ConfigurableProductSection.generateConfigure}}" stepKey="clickGenerateConfigure"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + + <!--Go to frontend and check image and price--> + <amOnPage url="{{StorefrontProductPage.url($$createConfigProductCreateConfigurableProduct.custom_attributes[url_key]$$)}}" stepKey="goToProductPage"/> + + <actionGroup ref="AssertOptionImageAndPriceInStorefrontProductActionGroup" stepKey="assertFirstOptionImageAndPriceInStorefrontProductPage"> + <argument name="label" value="$$getConfigAttributeOption1CreateConfigurableProduct.label$$"/> + <argument name="image" value="{{ImageUpload.filename}}"/> + <argument name="price" value="10"/> + </actionGroup> + + <actionGroup ref="AssertOptionImageAndPriceInStorefrontProductActionGroup" stepKey="assertSecondOptionImageAndPriceInStorefrontProductPage"> + <argument name="label" value="$$getConfigAttributeOption2CreateConfigurableProduct.label$$"/> + <argument name="image" value="{{ImageUpload_1.filename}}"/> + <argument name="price" value="20"/> + </actionGroup> + + <actionGroup ref="AssertOptionImageAndPriceInStorefrontProductActionGroup" stepKey="assertThirdOptionImageAndPriceInStorefrontProductPage"> + <argument name="label" value="{{colorDefaultProductAttribute1.name}}"/> + <argument name="image" value="{{ImageUpload3.filename}}"/> + <argument name="price" value="30"/> + </actionGroup> + </test> +</tests> From 4fd2e310703db7f4f13904bbb8743f19058cd0b3 Mon Sep 17 00:00:00 2001 From: Karan Shah <karan.shah@krishtechnolabs.com> Date: Mon, 8 Apr 2019 15:29:15 +0530 Subject: [PATCH 407/603] Typography_change --- .../Adminhtml/Catalog/Product/Edit/Tab/Attributes/Extend.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/Extend.php b/app/code/Magento/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/Extend.php index 0e21e566d5e75..4654144ce6873 100644 --- a/app/code/Magento/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/Extend.php +++ b/app/code/Magento/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/Extend.php @@ -75,7 +75,7 @@ public function getElementHtml() } /** - * Execute method getElementHtml from parrent class + * Execute method getElementHtml from parent class * * @return string */ From caf6843e1b8cb61f3f9b58adbda81f08b58ea0a2 Mon Sep 17 00:00:00 2001 From: vagrant <eino.keskitalo@vaimo.com> Date: Mon, 8 Apr 2019 16:12:17 +0200 Subject: [PATCH 408/603] Remove unused payment variable from order data. The $payment variable is overwritten in the foreach loop. --- .../testsuite/Magento/Sales/_files/order_list.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_list.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_list.php index 1f4253f18487c..8a1da8e8a3eb1 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/order_list.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_list.php @@ -24,8 +24,7 @@ 'subtotal' => 120.00, 'base_grand_total' => 120.00, 'store_id' => 1, - 'website_id' => 1, - 'payment' => $payment + 'website_id' => 1 ], [ 'increment_id' => '100000003', @@ -35,8 +34,7 @@ 'base_grand_total' => 140.00, 'subtotal' => 140.00, 'store_id' => 0, - 'website_id' => 0, - 'payment' => $payment + 'website_id' => 0 ], [ 'increment_id' => '100000004', @@ -46,8 +44,7 @@ 'base_grand_total' => 140.00, 'subtotal' => 140.00, 'store_id' => 1, - 'website_id' => 1, - 'payment' => $payment + 'website_id' => 1 ], ]; From 2f23922752aa0d1d713a5f285a52b4cf5fe46202 Mon Sep 17 00:00:00 2001 From: Evgeny Petrov <evgeny_petrov@epam.com> Date: Mon, 8 Apr 2019 17:19:46 +0300 Subject: [PATCH 409/603] MAGETWO-98584: Google chart API used by Magento dashboard scheduled to be turned off --- .../Magento/Backend/Controller/Adminhtml/DashboardTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php index 89f1e5e5d53d6..07af21505f180 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php @@ -21,8 +21,6 @@ public function testAjaxBlockAction() public function testTunnelAction() { - $this->markTestSkipped('MAGETWO-98800: TunnelAction fails when Google Chart API is not available'); - $testUrl = \Magento\Backend\Block\Dashboard\Graph::API_URL . '?cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World'; $handle = curl_init(); curl_setopt($handle, CURLOPT_URL, $testUrl); From 241450e4e669885ff229ab192a9237498c1b1214 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Mon, 8 Apr 2019 16:41:45 +0200 Subject: [PATCH 410/603] [Checkout Coverage] Place order for guest --- .../Model/Resolver/PlaceOrder.php | 7 + .../GraphQl/Quote/Guest/PlaceOrderTest.php | 134 ++++++++++++++++++ .../Quote/_files/guest/set_guest_email.php | 24 ++++ 3 files changed, 165 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/guest/set_guest_email.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php index 3bd46a664f2ab..1672474bb3ddd 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php @@ -65,6 +65,13 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); + if ($context->getUserId() === 0) { + if (!$cart->getCustomerEmail()) { + throw new GraphQlInputException(__("Guest email for cart is missing. Please enter")); + } + $cart->setCheckoutMethod(CartManagementInterface::METHOD_GUEST); + } + try { $orderId = $this->cartManagement->placeOrder($cart->getId()); $order = $this->orderRepository->get($orderId); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php new file mode 100644 index 0000000000000..d102a8eb72df2 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php @@ -0,0 +1,134 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\Framework\Registry; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\ResourceModel\Order\CollectionFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for placing an order for guest + */ +class PlaceOrderTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @var CollectionFactory + */ + private $orderCollectionFactory; + + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + + /** + * @var Registry + */ + private $registry; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->orderCollectionFactory = $objectManager->get(CollectionFactory::class); + $this->orderRepository = $objectManager->get(OrderRepositoryInterface::class); + $this->registry = Bootstrap::getObjectManager()->get(Registry::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/set_guest_email.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testPlaceOrder() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query); + + self::assertArrayHasKey('placeOrder', $response); + self::assertArrayHasKey('order_id', $response['placeOrder']['order']); + self::assertEquals($reservedOrderId, $response['placeOrder']['order']['order_id']); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testPlaceOrderWithNoEmail() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessage("Guest email for cart is missing. Please enter"); + $this->graphQlQuery($query); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +mutation { + placeOrder(input: {cart_id: "{$maskedQuoteId}"}) { + order { + order_id + } + } +} +QUERY; + } + + /** + * @inheritdoc + */ + public function tearDown() + { + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', true); + + $orderCollection = $this->orderCollectionFactory->create(); + foreach ($orderCollection as $order) { + $this->orderRepository->delete($order); + } + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', false); + + parent::tearDown(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/guest/set_guest_email.php b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/guest/set_guest_email.php new file mode 100644 index 0000000000000..4e214f4310044 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/guest/set_guest_email.php @@ -0,0 +1,24 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Model\QuoteFactory; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\TestFramework\Helper\Bootstrap; + +/** @var QuoteFactory $quoteFactory */ +$quoteFactory = Bootstrap::getObjectManager()->get(QuoteFactory::class); +/** @var CartRepositoryInterface $cartRepository */ +$cartRepository = Bootstrap::getObjectManager()->get(CartRepositoryInterface::class); +/** @var QuoteResource $quoteResource */ +$quoteResource = Bootstrap::getObjectManager()->get(QuoteResource::class); + +$quote = $quoteFactory->create(); +$quoteResource->load($quote, 'test_quote', 'reserved_order_id'); + +$quote->setCustomerEmail('customer@example.com'); +$cartRepository->save($quote); From c7a770fa1efb6fb966f2ee1342fadb4c496f880f Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Mon, 8 Apr 2019 10:26:38 -0500 Subject: [PATCH 411/603] MC-15440: Product Page Gallery Load Optimization --- app/code/Magento/Catalog/Helper/Image.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Helper/Image.php b/app/code/Magento/Catalog/Helper/Image.php index cc2a1cd7cb481..9b8d0ad75a8c9 100644 --- a/app/code/Magento/Catalog/Helper/Image.php +++ b/app/code/Magento/Catalog/Helper/Image.php @@ -765,7 +765,7 @@ protected function getImageFile() protected function parseSize($string) { $size = explode('x', strtolower($string)); - if (sizeof($size) == 2) { + if (count($size) == 2) { return ['width' => $size[0] > 0 ? $size[0] : null, 'height' => $size[1] > 0 ? $size[1] : null]; } return false; From 02a65d02b25acb73e243cac8abf03cc55cb68335 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Mon, 8 Apr 2019 10:27:17 -0500 Subject: [PATCH 412/603] MAGETWO-93628: Shopping cart is emptied after reset password procedure --- app/code/Magento/Customer/Model/AccountManagement.php | 5 +---- .../Customer/Test/Unit/Model/AccountManagementTest.php | 9 +++------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index d86286bc2fcb9..0440eb161e9e0 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -1066,10 +1066,7 @@ public function validate(CustomerInterface $customer) $result = $this->getEavValidator()->isValid($customerModel); if ($result === false && is_array($this->getEavValidator()->getMessages())) { return $validationResults->setIsValid(false)->setMessages( - call_user_func_array( - 'array_merge', - $this->getEavValidator()->getMessages() - ) + array_merge(...$this->getEavValidator()->getMessages()) ); } return $validationResults->setIsValid(true)->setMessages([]); diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index aa901e8a2e978..24a96a929a067 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -1238,8 +1238,7 @@ public function testInitiatePasswordResetEmailReminder() $storeId = 1; - mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX); - $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true)); + $hash = hash('sha256', microtime() . random_int(PHP_INT_MIN, PHP_INT_MAX)); $this->emailNotificationMock->expects($this->once()) ->method('passwordReminder') @@ -1263,8 +1262,7 @@ public function testInitiatePasswordResetEmailReset() $templateIdentifier = 'Template Identifier'; $sender = 'Sender'; - mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX); - $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true)); + $hash = hash('sha256', microtime() . random_int(PHP_INT_MIN, PHP_INT_MAX)); $this->emailNotificationMock->expects($this->once()) ->method('passwordResetConfirmation') @@ -1288,8 +1286,7 @@ public function testInitiatePasswordResetNoTemplate() $templateIdentifier = 'Template Identifier'; $sender = 'Sender'; - mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX); - $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true)); + $hash = hash('sha256', microtime() . random_int(PHP_INT_MIN, PHP_INT_MAX)); $this->prepareInitiatePasswordReset($email, $templateIdentifier, $sender, $storeId, $customerId, $hash); From 05f345873c3e9567569a5dd63949f490acf0f37a Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Mon, 8 Apr 2019 18:06:26 +0200 Subject: [PATCH 413/603] Additional test cases --- .../GraphQl/Quote/Guest/PlaceOrderTest.php | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php index d102a8eb72df2..648b8265ee674 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php @@ -97,6 +97,145 @@ public function testPlaceOrderWithNoEmail() $this->graphQlQuery($query); } + /** + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/set_guest_email.php + */ + public function testPlaceOrderWithNoItemsInCart() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessage( + 'Unable to place order: A server error stopped your order from being placed. ' . + 'Please try to place your order again' + ); + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/set_guest_email.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testPlaceOrderWithNoShippingAddress() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessage( + 'Unable to place order: Some addresses can\'t be used due to the configurations for specific countries' + ); + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/set_guest_email.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testPlaceOrderWithNoShippingMethod() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessage( + 'Unable to place order: The shipping method is missing. Select the shipping method and try again' + ); + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/set_guest_email.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php + */ + public function testPlaceOrderWithNoBillingAddress() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessageRegExp( + '/Unable to place order: Please check the billing address information*/' + ); + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/set_guest_email.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php + */ + public function testPlaceOrderWithNoPaymentMethod() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessage('Unable to place order: Enter a valid payment method and try again'); + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/set_guest_email.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/set_simple_product_out_of_stock.php + */ + public function testPlaceOrderWithOutOfStockProduct() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessage('Unable to place order: Some of the products are out of stock'); + $this->graphQlQuery($query); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testPlaceOrderOfAnotherCustomerCart() + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + $query = $this->getQuery($maskedQuoteId); + + self::expectExceptionMessageRegExp('/The current user cannot perform operations on cart*/'); + $this->graphQlQuery($query); + } + /** * @param string $maskedQuoteId * @return string From 3352abdc715ef0446684d4e866da1d72e56d4fc5 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 8 Apr 2019 11:19:40 -0500 Subject: [PATCH 414/603] GraphQL-544: Replace deprecated fixtures in RemoveItemFromCartTest --- .../Quote/Customer/RemoveItemFromCartTest.php | 209 +++++++----------- .../GetQuoteItemIdByReservedQuoteIdAndSku.php | 66 ++++++ .../Quote/Guest/RemoveItemFromCartTest.php | 143 ++++++------ 3 files changed, 212 insertions(+), 206 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/GetQuoteItemIdByReservedQuoteIdAndSku.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php index 5f023086e89e1..1b6d1f3b14383 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php @@ -7,11 +7,9 @@ namespace Magento\GraphQl\Quote\Customer; -use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\GraphQl\Quote\GetQuoteItemIdByReservedQuoteIdAndSku; use Magento\Integration\Api\CustomerTokenServiceInterface; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -26,49 +24,37 @@ class RemoveItemFromCartTest extends GraphQlAbstract private $customerTokenService; /** - * @var QuoteResource + * @var GetMaskedQuoteIdByReservedOrderId */ - private $quoteResource; + private $getMaskedQuoteIdByReservedOrderId; /** - * @var QuoteFactory + * @var GetQuoteItemIdByReservedQuoteIdAndSku */ - private $quoteFactory; - - /** - * @var QuoteIdToMaskedQuoteIdInterface - */ - private $quoteIdToMaskedId; - - /** - * @var ProductRepositoryInterface - */ - private $productRepository; + private $getQuoteItemIdByReservedQuoteIdAndSku; protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); - $this->productRepository = $objectManager->get(ProductRepositoryInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->getQuoteItemIdByReservedQuoteIdAndSku = $objectManager->get( + GetQuoteItemIdByReservedQuoteIdAndSku::class + ); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ public function testRemoveItemFromCart() { - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, 'test_quote', 'reserved_order_id'); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); - $itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId(); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $itemId = $this->getQuoteItemIdByReservedQuoteIdAndSku->execute('test_quote', 'simple_product'); - $query = $this->prepareMutationQuery($maskedQuoteId, $itemId); + $query = $this->getQuery($maskedQuoteId, $itemId); $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); $this->assertArrayHasKey('removeItemFromCart', $response); @@ -83,116 +69,24 @@ public function testRemoveItemFromCart() */ public function testRemoveItemFromNonExistentCart() { - $query = $this->prepareMutationQuery('non_existent_masked_id', 1); + $query = $this->getQuery('non_existent_masked_id', 1); $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ public function testRemoveNonExistentItem() { - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, 'test_quote', 'reserved_order_id'); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $notExistentItemId = 999; $this->expectExceptionMessage("Cart doesn't contain the {$notExistentItemId} item."); - $query = $this->prepareMutationQuery($maskedQuoteId, $notExistentItemId); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); - } - - /** - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php - */ - public function testRemoveItemIfItemIsNotBelongToCart() - { - $firstQuote = $this->quoteFactory->create(); - $this->quoteResource->load($firstQuote, 'test_quote', 'reserved_order_id'); - $firstQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$firstQuote->getId()); - - $secondQuote = $this->quoteFactory->create(); - $this->quoteResource->load( - $secondQuote, - 'test_order_with_virtual_product_without_address', - 'reserved_order_id' - ); - $secondQuote->setCustomerId(1); - $this->quoteResource->save($secondQuote); - $secondQuoteItemId = (int)$secondQuote - ->getItemByProduct($this->productRepository->get('virtual-product')) - ->getId(); - - $this->expectExceptionMessage("Cart doesn't contain the {$secondQuoteItemId} item."); - - $query = $this->prepareMutationQuery($firstQuoteMaskedId, $secondQuoteItemId); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); - } - - /** - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_virtual.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_virtual_product.php - */ - public function testRemoveItemFromGuestCart() - { - $guestQuote = $this->quoteFactory->create(); - $this->quoteResource->load( - $guestQuote, - 'test_quote', - 'reserved_order_id' - ); - $guestQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$guestQuote->getId()); - $guestQuoteItemId = (int)$guestQuote - ->getItemByProduct($this->productRepository->get('virtual-product')) - ->getId(); - - $this->expectExceptionMessage( - "The current user cannot perform operations on cart \"$guestQuoteMaskedId\"" - ); - - $query = $this->prepareMutationQuery($guestQuoteMaskedId, $guestQuoteItemId); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); - } - - /** - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/Customer/_files/three_customers.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php - */ - public function testRemoveItemFromAnotherCustomerCart() - { - $anotherCustomerQuote = $this->quoteFactory->create(); - $this->quoteResource->load( - $anotherCustomerQuote, - 'test_order_with_virtual_product_without_address', - 'reserved_order_id' - ); - $anotherCustomerQuote->setCustomerId(2); - $this->quoteResource->save($anotherCustomerQuote); - - $anotherCustomerQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$anotherCustomerQuote->getId()); - $anotherCustomerQuoteItemId = (int)$anotherCustomerQuote - ->getItemByProduct($this->productRepository->get('virtual-product')) - ->getId(); - - $this->expectExceptionMessage( - "The current user cannot perform operations on cart \"$anotherCustomerQuoteMaskedId\"" - ); - - $query = $this->prepareMutationQuery($anotherCustomerQuoteMaskedId, $anotherCustomerQuoteItemId); + $query = $this->getQuery($maskedQuoteId, $notExistentItemId); $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } @@ -240,12 +134,77 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ]; } + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_and_address.php + */ + public function testRemoveItemIfItemIsNotBelongToCart() + { + $firstQuoteMaskedId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $secondQuoteItemId = $this->getQuoteItemIdByReservedQuoteIdAndSku->execute( + 'test_order_with_virtual_product', + 'virtual-product' + ); + + $this->expectExceptionMessage("Cart doesn't contain the {$secondQuoteItemId} item."); + + $query = $this->getQuery($firstQuoteMaskedId, $secondQuoteItemId); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testRemoveItemFromGuestCart() + { + $guestQuoteMaskedId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $guestQuoteItemId = $this->getQuoteItemIdByReservedQuoteIdAndSku->execute('test_quote', 'simple_product'); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$guestQuoteMaskedId\"" + ); + + $query = $this->getQuery($guestQuoteMaskedId, $guestQuoteItemId); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testRemoveItemFromAnotherCustomerCart() + { + $anotherCustomerQuoteMaskedId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $anotherCustomerQuoteItemId = $this->getQuoteItemIdByReservedQuoteIdAndSku->execute( + 'test_quote', + 'simple_product' + ); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$anotherCustomerQuoteMaskedId\"" + ); + + $query = $this->getQuery($anotherCustomerQuoteMaskedId, $anotherCustomerQuoteItemId); + $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer2@search.example.com')); + } + /** * @param string $maskedQuoteId * @param int $itemId * @return string */ - private function prepareMutationQuery(string $maskedQuoteId, int $itemId): string + private function getQuery(string $maskedQuoteId, int $itemId): string { return <<<QUERY mutation { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/GetQuoteItemIdByReservedQuoteIdAndSku.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/GetQuoteItemIdByReservedQuoteIdAndSku.php new file mode 100644 index 0000000000000..6f027babc0e27 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/GetQuoteItemIdByReservedQuoteIdAndSku.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\Quote\Model\QuoteFactory; + +/** + * Get quote item id by reserved order id and product sku + */ +class GetQuoteItemIdByReservedQuoteIdAndSku +{ + /** + * @var QuoteFactory + */ + private $quoteFactory; + + /** + * @var QuoteResource + */ + private $quoteResource; + + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @param QuoteFactory $quoteFactory + * @param QuoteResource $quoteResource + * @param ProductRepositoryInterface $productRepository + */ + public function __construct( + QuoteFactory $quoteFactory, + QuoteResource $quoteResource, + ProductRepositoryInterface $productRepository + ) { + $this->quoteFactory = $quoteFactory; + $this->quoteResource = $quoteResource; + $this->productRepository = $productRepository; + } + + /** + * Get quote item id by reserved order id and product sku + * + * @param string $reservedOrderId + * @param string $sku + * @return int + * @throws NoSuchEntityException + */ + public function execute(string $reservedOrderId, string $sku): int + { + $quote = $this->quoteFactory->create(); + $this->quoteResource->load($quote, $reservedOrderId, 'reserved_order_id'); + $product = $this->productRepository->get($sku); + + return (int)$quote->getItemByProduct($product)->getId(); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php index a306b29e51197..294230c658aa0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php @@ -7,10 +7,8 @@ namespace Magento\GraphQl\Quote\Guest; -use Magento\Quote\Model\QuoteFactory; -use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\GraphQl\Quote\GetQuoteItemIdByReservedQuoteIdAndSku; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -20,45 +18,35 @@ class RemoveItemFromCartTest extends GraphQlAbstract { /** - * @var QuoteResource + * @var GetMaskedQuoteIdByReservedOrderId */ - private $quoteResource; + private $getMaskedQuoteIdByReservedOrderId; /** - * @var QuoteFactory + * @var GetQuoteItemIdByReservedQuoteIdAndSku */ - private $quoteFactory; - - /** - * @var QuoteIdToMaskedQuoteIdInterface - */ - private $quoteIdToMaskedId; - - /** - * @var ProductRepositoryInterface - */ - private $productRepository; + private $getQuoteItemIdByReservedQuoteIdAndSku; protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); - $this->productRepository = $objectManager->get(ProductRepositoryInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->getQuoteItemIdByReservedQuoteIdAndSku = $objectManager->get( + GetQuoteItemIdByReservedQuoteIdAndSku::class + ); } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ public function testRemoveItemFromCart() { - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, 'test_order_with_simple_product_without_address', 'reserved_order_id'); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); - $itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId(); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $itemId = $this->getQuoteItemIdByReservedQuoteIdAndSku->execute('test_quote', 'simple_product'); - $query = $this->prepareMutationQuery($maskedQuoteId, $itemId); + $query = $this->getQuery($maskedQuoteId, $itemId); $response = $this->graphQlQuery($query); $this->assertArrayHasKey('removeItemFromCart', $response); @@ -72,69 +60,23 @@ public function testRemoveItemFromCart() */ public function testRemoveItemFromNonExistentCart() { - $query = $this->prepareMutationQuery('non_existent_masked_id', 1); + $query = $this->getQuery('non_existent_masked_id', 1); $this->graphQlQuery($query); } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ public function testRemoveNonExistentItem() { - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, 'test_order_with_simple_product_without_address', 'reserved_order_id'); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $notExistentItemId = 999; $this->expectExceptionMessage("Cart doesn't contain the {$notExistentItemId} item."); - $query = $this->prepareMutationQuery($maskedQuoteId, $notExistentItemId); - $this->graphQlQuery($query); - } - - /** - * Test mutation is only able to remove quote item belonging to the requested cart - * - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php - */ - public function testRemoveItemIfItemIsNotBelongToCart() - { - $firstQuote = $this->quoteFactory->create(); - $this->quoteResource->load($firstQuote, 'test_order_with_simple_product_without_address', 'reserved_order_id'); - $firstQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$firstQuote->getId()); - - $secondQuote = $this->quoteFactory->create(); - $this->quoteResource->load( - $secondQuote, - 'test_order_with_virtual_product_without_address', - 'reserved_order_id' - ); - $secondQuoteItemId = (int)$secondQuote - ->getItemByProduct($this->productRepository->get('virtual-product')) - ->getId(); - - $this->expectExceptionMessage("Cart doesn't contain the {$secondQuoteItemId} item."); - - $query = $this->prepareMutationQuery($firstQuoteMaskedId, $secondQuoteItemId); - $this->graphQlQuery($query); - } - - /** - * Test mutation is only able to remove quote item belonging to the requested cart - * - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php - */ - public function testRemoveItemFromCustomerCart() - { - $customerQuote = $this->quoteFactory->create(); - $this->quoteResource->load($customerQuote, 'test_order_1', 'reserved_order_id'); - $customerQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$customerQuote->getId()); - $customerQuoteItemId = (int)$customerQuote->getItemByProduct($this->productRepository->get('simple'))->getId(); - - $this->expectExceptionMessage("The current user cannot perform operations on cart \"$customerQuoteMaskedId\""); - - $query = $this->prepareMutationQuery($customerQuoteMaskedId, $customerQuoteItemId); + $query = $this->getQuery($maskedQuoteId, $notExistentItemId); $this->graphQlQuery($query); } @@ -181,12 +123,51 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ]; } + /** + * _security + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php + */ + public function testRemoveItemIfItemIsNotBelongToCart() + { + $firstQuoteMaskedId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $secondQuoteItemId = $this->getQuoteItemIdByReservedQuoteIdAndSku->execute( + 'test_order_with_virtual_product_without_address', + 'virtual-product' + ); + + $this->expectExceptionMessage("Cart doesn't contain the {$secondQuoteItemId} item."); + + $query = $this->getQuery($firstQuoteMaskedId, $secondQuoteItemId); + $this->graphQlQuery($query); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testRemoveItemFromCustomerCart() + { + $customerQuoteMaskedId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $customerQuoteItemId = $this->getQuoteItemIdByReservedQuoteIdAndSku->execute('test_quote', 'simple_product'); + + $this->expectExceptionMessage("The current user cannot perform operations on cart \"$customerQuoteMaskedId\""); + + $query = $this->getQuery($customerQuoteMaskedId, $customerQuoteItemId); + $this->graphQlQuery($query); + } + /** * @param string $maskedQuoteId * @param int $itemId * @return string */ - private function prepareMutationQuery(string $maskedQuoteId, int $itemId): string + private function getQuery(string $maskedQuoteId, int $itemId): string { return <<<QUERY mutation { From 1c98b32f62a4f2433adb4b01d144fcfc9e12ebf7 Mon Sep 17 00:00:00 2001 From: "Leandro F. L" <lfluvisotto@gmail.com> Date: Mon, 8 Apr 2019 13:53:10 -0300 Subject: [PATCH 415/603] Fix > Exception #0 (BadMethodCallException): Missing required argument of Magento\Msrp\Pricing\MsrpPriceCalculator. --- app/code/Magento/Msrp/Pricing/MsrpPriceCalculator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Msrp/Pricing/MsrpPriceCalculator.php b/app/code/Magento/Msrp/Pricing/MsrpPriceCalculator.php index 3d1e5ef0b8e6c..af5a29eb288ea 100644 --- a/app/code/Magento/Msrp/Pricing/MsrpPriceCalculator.php +++ b/app/code/Magento/Msrp/Pricing/MsrpPriceCalculator.php @@ -23,7 +23,7 @@ class MsrpPriceCalculator implements MsrpPriceCalculatorInterface /** * @param array $msrpPriceCalculators */ - public function __construct(array $msrpPriceCalculators) + public function __construct(array $msrpPriceCalculators = []) { $this->msrpPriceCalculators = $this->getMsrpPriceCalculators($msrpPriceCalculators); } From fa079c94c9c0a6d3cd7d9dca3b52d3394de50934 Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta <riccardo.tempesta@gmail.com> Date: Fri, 29 Mar 2019 18:20:33 +0100 Subject: [PATCH 416/603] FIX for issue #21916 - Elasticsearch6 generation does not exist Magento was not checking concrete class while applying plugins, this commit prevents virtual types to be autogenerated --- .../Magento/Framework/Code/Generator.php | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Code/Generator.php b/lib/internal/Magento/Framework/Code/Generator.php index 4dec7d1a28146..ba4213f398008 100644 --- a/lib/internal/Magento/Framework/Code/Generator.php +++ b/lib/internal/Magento/Framework/Code/Generator.php @@ -8,6 +8,7 @@ use Magento\Framework\Code\Generator\DefinedClasses; use Magento\Framework\Code\Generator\EntityAbstract; use Magento\Framework\Code\Generator\Io; +use Magento\Framework\ObjectManager\ConfigInterface; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Phrase; use Magento\Framework\Filesystem\Driver\File; @@ -232,7 +233,21 @@ protected function shouldSkipGeneration($resultEntityType, $sourceClassName, $re { if (!$resultEntityType || !$sourceClassName) { return self::GENERATION_ERROR; - } elseif ($this->definedClasses->isClassLoadableFromDisk($resultClass)) { + } + + /** @var ConfigInterface $omConfig */ + $omConfig = $this->objectManager->get(ConfigInterface::class); + $virtualTypes = $omConfig->getVirtualTypes(); + + /** + * Do not try to autogenerate virtual types + * For example virtual types with names overlapping autogenerated suffixes + */ + if (isset($virtualTypes[$resultClass])) { + return self::GENERATION_SKIP; + } + + if ($this->definedClasses->isClassLoadableFromDisk($resultClass)) { $generatedFileName = $this->_ioObject->generateResultFileName($resultClass); /** * Must handle two edge cases: a competing process has generated the class and written it to disc already, @@ -244,9 +259,12 @@ protected function shouldSkipGeneration($resultEntityType, $sourceClassName, $re $this->_ioObject->includeFile($generatedFileName); } return self::GENERATION_SKIP; - } elseif (!isset($this->_generatedEntities[$resultEntityType])) { + } + + if (!isset($this->_generatedEntities[$resultEntityType])) { throw new \InvalidArgumentException('Unknown generation entity.'); } + return false; } } From b946dd0eae58d0cc0ccb9bb5e6be6b8aea4b7a77 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 8 Apr 2019 12:18:28 -0500 Subject: [PATCH 417/603] GraphQL-540: Replace deprecated Magento/Checkout/_files/quote_with_address_saved.php fixture in SetUpsShippingMethodsOnCartTest --- .../Ups/SetUpsShippingMethodsOnCartTest.php | 49 ++++++++++--------- .../Ups/_files/enable_ups_shipping_method.php | 1 + .../enable_ups_shipping_method_rollback.php | 1 + 3 files changed, 29 insertions(+), 22 deletions(-) rename dev/tests/integration/testsuite/Magento/{ => GraphQl}/Ups/_files/enable_ups_shipping_method.php (87%) rename dev/tests/integration/testsuite/Magento/{ => GraphQl}/Ups/_files/enable_ups_shipping_method_rollback.php (84%) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index 838017b3455df..a46cf6f0e16b7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -55,39 +55,44 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php * - * @param string $carrierMethodCode - * @param string $carrierMethodLabel + * @param string $methodCode + * @param string $methodLabel * @dataProvider availableForCartShippingMethods */ - public function testSetAvailableForCartUpsShippingMethod(string $carrierMethodCode, string $carrierMethodLabel) + public function testSetAvailableUpsShippingMethodOnCart(string $methodCode, string $methodLabel) { $quoteReservedId = 'test_quote'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - $query = $this->getQuery( - $maskedQuoteId, - $shippingAddressId, - self::CARRIER_CODE, - $carrierMethodCode - ); + $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); + $response = $this->graphQlQuery($query); - $response = $this->sendRequestWithToken($query); + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses']; - $expectedResult = [ - 'carrier_code' => self::CARRIER_CODE, - 'method_code' => $carrierMethodCode, - 'label' => self::CARRIER_LABEL . ' - ' . $carrierMethodLabel, - ]; - self::assertEquals($addressesInformation[0]['selected_shipping_method'], $expectedResult); + $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('selected_shipping_method', $shippingAddress); + + self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); + + self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); + self::assertEquals( + self::CARRIER_LABEL . ' - ' . $methodLabel, + $shippingAddress['selected_shipping_method']['label'] + ); } /** @@ -96,7 +101,7 @@ public function testSetAvailableForCartUpsShippingMethod(string $carrierMethodCo * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php * * @param string $carrierMethodCode * @param string $carrierMethodLabel diff --git a/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method.php b/dev/tests/integration/testsuite/Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php similarity index 87% rename from dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method.php rename to dev/tests/integration/testsuite/Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php index 5c6c60866fafb..ffdc215d50a68 100644 --- a/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +// TODO: Should be removed in scope of https://github.com/magento/graphql-ce/issues/167 declare(strict_types=1); use Magento\Framework\App\Config\Storage\Writer; diff --git a/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method_rollback.php b/dev/tests/integration/testsuite/Magento/GraphQl/Ups/_files/enable_ups_shipping_method_rollback.php similarity index 84% rename from dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method_rollback.php rename to dev/tests/integration/testsuite/Magento/GraphQl/Ups/_files/enable_ups_shipping_method_rollback.php index 6d7894879f97b..243ec0217a0bb 100644 --- a/dev/tests/integration/testsuite/Magento/Ups/_files/enable_ups_shipping_method_rollback.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Ups/_files/enable_ups_shipping_method_rollback.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +// TODO: Should be removed in scope of https://github.com/magento/graphql-ce/issues/167 declare(strict_types=1); use Magento\Framework\App\Config\Storage\Writer; From c2d1f8fa571b1133c09a3b6344f44b2c364efecc Mon Sep 17 00:00:00 2001 From: "Leandro F. L" <lfluvisotto@gmail.com> Date: Mon, 8 Apr 2019 14:41:02 -0300 Subject: [PATCH 418/603] Remove all marketing get params on Varnish to minimize the cache objects (added facebook parameter) --- app/code/Magento/PageCache/etc/varnish4.vcl | 4 ++-- app/code/Magento/PageCache/etc/varnish5.vcl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/PageCache/etc/varnish4.vcl b/app/code/Magento/PageCache/etc/varnish4.vcl index c73c4e39170e6..198b2f6796e69 100644 --- a/app/code/Magento/PageCache/etc/varnish4.vcl +++ b/app/code/Magento/PageCache/etc/varnish4.vcl @@ -92,8 +92,8 @@ sub vcl_recv { } # Remove all marketing get parameters to minimize the cache objects - if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|mc_[a-z]+|utm_[a-z]+)=") { - set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|mc_[a-z]+|utm_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); + if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=") { + set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); set req.url = regsub(req.url, "[?|&]+$", ""); } diff --git a/app/code/Magento/PageCache/etc/varnish5.vcl b/app/code/Magento/PageCache/etc/varnish5.vcl index ea586858eff75..eac724ea7d0a5 100644 --- a/app/code/Magento/PageCache/etc/varnish5.vcl +++ b/app/code/Magento/PageCache/etc/varnish5.vcl @@ -93,8 +93,8 @@ sub vcl_recv { } # Remove all marketing get parameters to minimize the cache objects - if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|mc_[a-z]+|utm_[a-z]+)=") { - set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|mc_[a-z]+|utm_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); + if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=") { + set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); set req.url = regsub(req.url, "[?|&]+$", ""); } From fd0ebf8c075d13ec72385c3bc7b7860146af3a07 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 8 Apr 2019 13:05:06 -0500 Subject: [PATCH 419/603] GraphQL-479: [Test Coverage] 'ApplyCouponToCart' functionality --- .../Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php index 885e8705dc3d9..486f7cd0c27a7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php @@ -110,6 +110,7 @@ public function testApplyCouponToGuestCart() } /** + * _security * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent_generalusers.php * @magentoApiDataFixture Magento/Customer/_files/two_customers.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php From c11b10bbfeccd8f142cec31495d944bd7f94b9c5 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 8 Apr 2019 13:31:29 -0500 Subject: [PATCH 420/603] GraphQL-512: 'address.street' needs refactoring to support as many lines as defined by admin --- .../Model/Cart/QuoteAddress/Validator.php | 45 ------------------- .../Model/Cart/QuoteAddressFactory.php | 19 +++++++- .../Customer/SetBillingAddressOnCartTest.php | 2 +- .../Customer/SetShippingAddressOnCartTest.php | 2 +- .../Guest/SetBillingAddressOnCartTest.php | 2 +- .../Guest/SetShippingAddressOnCartTest.php | 2 +- 6 files changed, 22 insertions(+), 50 deletions(-) delete mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddress/Validator.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddress/Validator.php b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddress/Validator.php deleted file mode 100644 index 8cf2478d8f8b6..0000000000000 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddress/Validator.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\QuoteGraphQl\Model\Cart\QuoteAddress; - -use Magento\Customer\Helper\Address as AddressHelper; -use Magento\Framework\GraphQl\Exception\GraphQlInputException; -use Magento\Quote\Model\Quote\Address as QuoteAddress; - -/** - * Validate Quote Address - */ -class Validator -{ - /** - * @var AddressHelper - */ - private $addressHelper; - - /** - * @param AddressHelper $addressHelper - */ - public function __construct(AddressHelper $addressHelper) - { - $this->addressHelper = $addressHelper; - } - - /** - * Additional Quote Address validation for the GraphQl endpoint - * - * @param QuoteAddress $quoteAddress - * @throws GraphQlInputException - */ - public function validate(QuoteAddress $quoteAddress) - { - $maxAllowedLineCount = $this->addressHelper->getStreetLines(); - if (is_array($quoteAddress->getStreet()) && count($quoteAddress->getStreet()) > $maxAllowedLineCount) { - throw new GraphQlInputException(__('"Street Address" cannot contain more than %1 lines.', $maxAllowedLineCount)); - } - } -} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php index 582055bc6e13d..13d6a1d3dce70 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php @@ -7,6 +7,7 @@ namespace Magento\QuoteGraphQl\Model\Cart; +use Magento\Customer\Helper\Address as AddressHelper; use Magento\CustomerGraphQl\Model\Customer\Address\GetCustomerAddress; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; @@ -30,16 +31,24 @@ class QuoteAddressFactory */ private $getCustomerAddress; + /** + * @var AddressHelper + */ + private $addressHelper; + /** * @param BaseQuoteAddressFactory $quoteAddressFactory * @param GetCustomerAddress $getCustomerAddress + * @param AddressHelper $addressHelper */ public function __construct( BaseQuoteAddressFactory $quoteAddressFactory, - GetCustomerAddress $getCustomerAddress + GetCustomerAddress $getCustomerAddress, + AddressHelper $addressHelper ) { $this->quoteAddressFactory = $quoteAddressFactory; $this->getCustomerAddress = $getCustomerAddress; + $this->addressHelper = $addressHelper; } /** @@ -47,11 +56,19 @@ public function __construct( * * @param array $addressInput * @return QuoteAddress + * @throws GraphQlInputException */ public function createBasedOnInputData(array $addressInput): QuoteAddress { $addressInput['country_id'] = $addressInput['country_code'] ?? ''; + $maxAllowedLineCount = $this->addressHelper->getStreetLines(); + if (is_array($addressInput['street']) && count($addressInput['street']) > $maxAllowedLineCount) { + throw new GraphQlInputException( + __('"Street Address" cannot contain more than %1 lines.', $maxAllowedLineCount) + ); + } + $quoteAddress = $this->quoteAddressFactory->create(); $quoteAddress->addData($addressInput); return $quoteAddress; diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php index f5bc6276b10e8..b7b6fb5851666 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php @@ -495,7 +495,7 @@ public function testSetBillingAddressWithoutRequiredParameters(string $input, st /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php index f731ff5b89db2..0756ba6aeaf22 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php @@ -488,7 +488,7 @@ public function testSetMultipleNewShippingAddresses() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php index 421dbeb813a4c..d253b6f39b0db 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php @@ -314,7 +314,7 @@ public function testSetBillingAddressWithoutRequiredParameters(string $input, st } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php index 38a835ba89232..a6981e11799fb 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php @@ -247,7 +247,7 @@ public function testSetNewShippingAddressWithMissedRequiredParameters(string $in } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ From c4acbfffb4f4b9b201a9f1488160e6442affda24 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 8 Apr 2019 14:14:48 -0500 Subject: [PATCH 421/603] GraphQL-470: Creating/getting Cart queries should support Store context --- .../Model/Cart/GetCartForUser.php | 2 +- .../Quote/Customer/CreateEmptyCartTest.php | 118 ++++++++++++------ .../Quote/Guest/CreateEmptyCartTest.php | 85 ++++++++++--- 3 files changed, 150 insertions(+), 55 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/GetCartForUser.php b/app/code/Magento/QuoteGraphQl/Model/Cart/GetCartForUser.php index ea86dca06271a..3506ffc8c8792 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/GetCartForUser.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/GetCartForUser.php @@ -85,7 +85,7 @@ public function execute(string $cartHash, ?int $customerId): Quote } if ((int)$cart->getStoreId() !== (int)$this->storeManager->getStore()->getId()) { - throw new GraphQlAuthorizationException( + throw new GraphQlNoSuchEntityException( __( 'Wrong store code specified for cart "%masked_cart_id"', ['masked_cart_id' => $cartHash] diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php index 7539945456530..86b0d3010c0e3 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php @@ -7,8 +7,11 @@ namespace Magento\GraphQl\Quote\Customer; -use Magento\Framework\App\ResourceConnection; use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\Quote\Model\QuoteFactory; +use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; +use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; use Magento\Quote\Api\GuestCartRepositoryInterface; @@ -29,16 +32,39 @@ class CreateEmptyCartTest extends GraphQlAbstract private $customerTokenService; /** - * @var ResourceConnection + * @var QuoteResource */ - private $resourceConnection; + private $quoteResource; + + /** + * @var QuoteFactory + */ + private $quoteFactory; + + /** + * @var MaskedQuoteIdToQuoteIdInterface + */ + private $maskedQuoteIdToQuoteId; + + /** + * @var QuoteIdMaskFactory + */ + private $quoteIdMaskFactory; + + /** + * @var string + */ + private $maskedQuoteId; protected function setUp() { $objectManager = Bootstrap::getObjectManager(); $this->guestCartRepository = $objectManager->get(GuestCartRepositoryInterface::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); - $this->resourceConnection = $objectManager->get(ResourceConnection::class); + $this->quoteResource = $objectManager->get(QuoteResource::class); + $this->quoteFactory = $objectManager->get(QuoteFactory::class); + $this->maskedQuoteIdToQuoteId = $objectManager->get(MaskedQuoteIdToQuoteIdInterface::class); + $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); } /** @@ -46,27 +72,18 @@ protected function setUp() */ public function testCreateEmptyCart() { - $query = <<<QUERY -mutation { - createEmptyCart -} -QUERY; - - $customerToken = $this->customerTokenService->createCustomerAccessToken('customer@example.com', 'password'); - $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; - - $response = $this->graphQlQuery($query, [], '', $headerMap); + $query = $this->getQuery(); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMapWithCustomerToken()); self::assertArrayHasKey('createEmptyCart', $response); + self::assertNotEmpty($response['createEmptyCart']); - $maskedCartId = $response['createEmptyCart']; - $guestCart = $this->guestCartRepository->get($maskedCartId); + $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); + $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertEquals(1, $guestCart->getCustomer()->getId()); - self::assertSame('default', $guestCart->getStore()->getCode()); - - $this->deleteCreatedQuote($guestCart->getId()); + self::assertEquals('default', $guestCart->getStore()->getCode()); } /** @@ -75,40 +92,63 @@ public function testCreateEmptyCart() */ public function testCreateEmptyCartWithNotDefaultStore() { - $query = <<<QUERY -mutation { - createEmptyCart -} -QUERY; - - $customerToken = $this->customerTokenService->createCustomerAccessToken('customer@example.com', 'password'); - $headerMap = ['Authorization' => 'Bearer ' . $customerToken, 'Store' => 'fixture_second_store']; + $query = $this->getQuery(); + $headerMap = $this->getHeaderMapWithCustomerToken(); + $headerMap['Store'] = 'fixture_second_store'; $response = $this->graphQlQuery($query, [], '', $headerMap); self::assertArrayHasKey('createEmptyCart', $response); + self::assertNotEmpty($response['createEmptyCart']); - $maskedCartId = $response['createEmptyCart']; /* guestCartRepository is used for registered customer to get the cart hash */ - $guestCart = $this->guestCartRepository->get($maskedCartId); + $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); + $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertEquals(1, $guestCart->getCustomer()->getId()); - self::assertSame('fixture_second_store', $guestCart->getStore()->getCode()); + self::assertEquals('fixture_second_store', $guestCart->getStore()->getCode()); + } - $this->deleteCreatedQuote($guestCart->getId()); + /** + * @return string + */ + private function getQuery(): string + { + return <<<QUERY +mutation { + createEmptyCart +} +QUERY; } /** - * Delete active quote for customer by customer id. - * This is needed to have ability to create new quote for another store and not return the active one. - * @see QuoteManagement::createCustomerCart - * - * @param $quoteId + * @param string $username + * @param string $password + * @return array */ - private function deleteCreatedQuote($quoteId) + private function getHeaderMapWithCustomerToken( + string $username = 'customer@example.com', + string $password = 'password' + ): array { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } + + public function tearDown() { - $connection = $this->resourceConnection->getConnection(); - $connection->query('DELETE FROM quote WHERE entity_id = ' . $quoteId); + if (null !== $this->maskedQuoteId) { + $quoteId = $this->maskedQuoteIdToQuoteId->execute($this->maskedQuoteId); + + $quote = $this->quoteFactory->create(); + $this->quoteResource->load($quote, $quoteId); + $this->quoteResource->delete($quote); + + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $quoteIdMask->setQuoteId($quoteId) + ->delete(); + } + parent::tearDown(); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php index b283e7ef721a8..fe46a1edcdf1a 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php @@ -7,6 +7,10 @@ namespace Magento\GraphQl\Quote\Guest; +use Magento\Quote\Model\QuoteFactory; +use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; +use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; use Magento\Quote\Api\GuestCartRepositoryInterface; @@ -21,28 +25,55 @@ class CreateEmptyCartTest extends GraphQlAbstract */ private $guestCartRepository; + /** + * @var QuoteResource + */ + private $quoteResource; + + /** + * @var QuoteFactory + */ + private $quoteFactory; + + /** + * @var MaskedQuoteIdToQuoteIdInterface + */ + private $maskedQuoteIdToQuoteId; + + /** + * @var QuoteIdMaskFactory + */ + private $quoteIdMaskFactory; + + /** + * @var string + */ + private $maskedQuoteId; + protected function setUp() { $objectManager = Bootstrap::getObjectManager(); $this->guestCartRepository = $objectManager->get(GuestCartRepositoryInterface::class); + $this->quoteResource = $objectManager->get(QuoteResource::class); + $this->quoteFactory = $objectManager->get(QuoteFactory::class); + $this->maskedQuoteIdToQuoteId = $objectManager->get(MaskedQuoteIdToQuoteIdInterface::class); + $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); } public function testCreateEmptyCart() { - $query = <<<QUERY -mutation { - createEmptyCart -} -QUERY; + $query = $this->getQuery(); $response = $this->graphQlQuery($query); self::assertArrayHasKey('createEmptyCart', $response); + self::assertNotEmpty($response['createEmptyCart']); - $maskedCartId = $response['createEmptyCart']; - $guestCart = $this->guestCartRepository->get($maskedCartId); + $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); + $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertNull($guestCart->getCustomer()->getId()); + self::assertEquals('default', $guestCart->getStore()->getCode()); } /** @@ -50,22 +81,46 @@ public function testCreateEmptyCart() */ public function testCreateEmptyCartWithNotDefaultStore() { - $query = <<<QUERY -mutation { - createEmptyCart -} -QUERY; + $query = $this->getQuery(); $headerMap = ['Store' => 'fixture_second_store']; - $response = $this->graphQlQuery($query, [], '', $headerMap); self::assertArrayHasKey('createEmptyCart', $response); + self::assertNotEmpty($response['createEmptyCart']); - $maskedCartId = $response['createEmptyCart']; - $guestCart = $this->guestCartRepository->get($maskedCartId); + $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); + $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertNull($guestCart->getCustomer()->getId()); self::assertSame('fixture_second_store', $guestCart->getStore()->getCode()); } + + /** + * @return string + */ + private function getQuery(): string + { + return <<<QUERY +mutation { + createEmptyCart +} +QUERY; + } + + public function tearDown() + { + if (null !== $this->maskedQuoteId) { + $quoteId = $this->maskedQuoteIdToQuoteId->execute($this->maskedQuoteId); + + $quote = $this->quoteFactory->create(); + $this->quoteResource->load($quote, $quoteId); + $this->quoteResource->delete($quote); + + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $quoteIdMask->setQuoteId($quoteId) + ->delete(); + } + parent::tearDown(); + } } From 722afe3c9fe5c44783a54ae1b9d7feac33542d07 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 8 Apr 2019 15:08:33 -0500 Subject: [PATCH 422/603] GraphQL-512: 'address.street' needs refactoring to support as many lines as defined by admin --- .../Magento/GraphQl/Customer/CreateCustomerAddressTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php index 4ea19f08e3c1c..264a2c7de4783 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php @@ -13,6 +13,9 @@ use Magento\TestFramework\TestCase\GraphQlAbstract; use Magento\Integration\Api\CustomerTokenServiceInterface; +/** + * Create customer address tests + */ class CreateCustomerAddressTest extends GraphQlAbstract { /** From 9a4ff36ec163899b781efa6e52033ea1902dc166 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 8 Apr 2019 17:07:12 -0500 Subject: [PATCH 423/603] GraphQL-470: Creating/getting Cart queries should support Store context --- .../Magento/GraphQl/Quote/Customer/GetCartTest.php | 12 ++++++------ .../Magento/GraphQl/Quote/Guest/GetCartTest.php | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php index 8201c60144b15..19b72b9e3ca4c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php @@ -129,8 +129,8 @@ public function testGetInactiveCart() */ public function testGetCartWithNotDefaultStore() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_1_not_default_store'); - $query = $this->getCartQuery($maskedQuoteId); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1_not_default_store'); + $query = $this->getQuery($maskedQuoteId); $headerMap = $this->getHeaderMap(); $headerMap['Store'] = 'fixture_second_store'; @@ -150,8 +150,8 @@ public function testGetCartWithNotDefaultStore() */ public function testGetCartWithWrongStore() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_1'); - $query = $this->getCartQuery($maskedQuoteId); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); + $query = $this->getQuery($maskedQuoteId); $headerMap = $this->getHeaderMap(); $headerMap['Store'] = 'fixture_second_store'; @@ -167,8 +167,8 @@ public function testGetCartWithWrongStore() */ public function testGetCartWithNotExistingStore() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_1_not_default_store'); - $query = $this->getCartQuery($maskedQuoteId); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1_not_default_store'); + $query = $this->getQuery($maskedQuoteId); $headerMap = $this->getHeaderMap(); $headerMap['Store'] = 'not_existing_store'; diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php index 2b2ea4179ed02..832e15058a4ee 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php @@ -102,8 +102,8 @@ public function testGetInactiveCart() */ public function testGetCartWithNotDefaultStore() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_1_not_default_store_guest'); - $query = $this->getCartQuery($maskedQuoteId); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1_not_default_store_guest'); + $query = $this->getQuery($maskedQuoteId); $headerMap = ['Store' => 'fixture_second_store']; $response = $this->graphQlQuery($query, [], '', $headerMap); @@ -121,8 +121,8 @@ public function testGetCartWithNotDefaultStore() */ public function testGetCartWithWrongStore() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_1'); - $query = $this->getCartQuery($maskedQuoteId); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); + $query = $this->getQuery($maskedQuoteId); $headerMap = ['Store' => 'fixture_second_store']; $this->graphQlQuery($query, [], '', $headerMap); @@ -137,10 +137,10 @@ public function testGetCartWithWrongStore() */ public function testGetCartWithNotExistingStore() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_1_not_default_store_guest'); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1_not_default_store_guest'); $headerMap['Store'] = 'not_existing_store'; - $query = $this->getCartQuery($maskedQuoteId); + $query = $this->getQuery($maskedQuoteId); $this->graphQlQuery($query, [], '', $headerMap); } From 3f0530a6d408a2978397550570c2cffe5c5786ce Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 9 Apr 2019 00:22:07 -0500 Subject: [PATCH 424/603] GraphQL-479: [Test Coverage] 'ApplyCouponToCart' functionality --- .../Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php | 1 + .../Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php index 486f7cd0c27a7..f0d9400b1866b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php @@ -174,6 +174,7 @@ public function testApplyCouponToNonExistentCart() */ public function testApplyExpiredCoupon() { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/574'); $couponCode = '2?ds5!2d'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $couponCode); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php index 4fd1c713db5d4..045a28834e0dd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php @@ -139,6 +139,7 @@ public function testApplyCouponToNonExistentCart() */ public function testApplyExpiredCoupon() { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/574'); $couponCode = '2?ds5!2d'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $couponCode); From d62d2784d1a121e590c2224f2e3010dc2feca25c Mon Sep 17 00:00:00 2001 From: niravkrish <nirav.patel@krishtechnolabs.com> Date: Tue, 9 Apr 2019 12:10:12 +0530 Subject: [PATCH 425/603] Fixed - Admin Order Create Full tax summary calculation missing --- .../adminhtml/templates/order/create/totals/tax.phtml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals/tax.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals/tax.phtml index 92139896273da..643146f7bb5cb 100755 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals/tax.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals/tax.phtml @@ -33,7 +33,6 @@ $taxAmount = $block->getTotal()->getValue(); <?php $percent = $info['percent']; ?> <?php $amount = $info['amount']; ?> <?php $rates = $info['rates']; ?> - <?php $isFirst = 1; ?> <?php foreach ($rates as $rate): ?> <tr class="summary-details-<?= /* @escapeNotVerified */ $taxIter ?> summary-details<?php if ($isTop): echo ' summary-details-first'; endif; ?>" style="display:none;"> @@ -44,13 +43,10 @@ $taxAmount = $block->getTotal()->getValue(); <?php endif; ?> <br /> </td> - <?php if ($isFirst): ?> - <td style="<?= /* @escapeNotVerified */ $block->getTotal()->getStyle() ?>" class="admin__total-amount" rowspan="<?= count($rates) ?>"> - <?= /* @escapeNotVerified */ $block->formatPrice($amount) ?> - </td> - <?php endif; ?> + <td style="<?= /* @escapeNotVerified */ $block->getTotal()->getStyle() ?>" class="admin__total-amount"> + <?= /* @escapeNotVerified */ $block->formatPrice(($amount*(float)$rate['percent'])/$percent) ?> + </td> </tr> - <?php $isFirst = 0; ?> <?php $isTop = 0; ?> <?php endforeach; ?> <?php endforeach; ?> From 83cb9a054fe9908c9e22682b1d62353336363568 Mon Sep 17 00:00:00 2001 From: Evgeny Petrov <evgeny_petrov@epam.com> Date: Tue, 9 Apr 2019 11:03:55 +0300 Subject: [PATCH 426/603] MAGETWO-98584: Google chart API used by Magento dashboard scheduled to be turned off --- .../Magento/Backend/Block/Dashboard/Graph.php | 79 +++++++++++-------- .../Controller/Adminhtml/DashboardTest.php | 8 ++ 2 files changed, 52 insertions(+), 35 deletions(-) diff --git a/app/code/Magento/Backend/Block/Dashboard/Graph.php b/app/code/Magento/Backend/Block/Dashboard/Graph.php index 71a6cf4e938f2..56e7ab6186ada 100644 --- a/app/code/Magento/Backend/Block/Dashboard/Graph.php +++ b/app/code/Magento/Backend/Block/Dashboard/Graph.php @@ -320,7 +320,8 @@ public function getChartUrl($directUrl = true) foreach ($this->getAllSeries() as $index => $serie) { $thisdataarray = $serie; - for ($j = 0; $j < sizeof($thisdataarray); $j++) { + $count = count($thisdataarray); + for ($j = 0; $j < $count; $j++) { $currentvalue = $thisdataarray[$j]; if (is_numeric($currentvalue)) { $ylocation = $yorigin + $currentvalue; @@ -341,45 +342,13 @@ public function getChartUrl($directUrl = true) $valueBuffer = []; - if (sizeof($this->_axisLabels) > 0) { + if (count($this->_axisLabels) > 0) { $params['chxt'] = implode(',', array_keys($this->_axisLabels)); $indexid = 0; foreach ($this->_axisLabels as $idx => $labels) { if ($idx == 'x') { - /** - * Format date - */ - foreach ($this->_axisLabels[$idx] as $_index => $_label) { - if ($_label != '') { - $period = new \DateTime($_label, new \DateTimeZone($timezoneLocal)); - switch ($this->getDataHelper()->getParam('period')) { - case '24h': - $this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime( - $period->setTime($period->format('H'), 0, 0), - \IntlDateFormatter::NONE, - \IntlDateFormatter::SHORT - ); - break; - case '7d': - case '1m': - $this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime( - $period, - \IntlDateFormatter::SHORT, - \IntlDateFormatter::NONE - ); - break; - case '1y': - case '2y': - $this->_axisLabels[$idx][$_index] = date('m/Y', strtotime($_label)); - break; - } - } else { - $this->_axisLabels[$idx][$_index] = ''; - } - } - + $this->formatAxisLabelDate($idx, $timezoneLocal); $tmpstring = implode('|', $this->_axisLabels[$idx]); - $valueBuffer[] = $indexid . ":|" . $tmpstring; } elseif ($idx == 'y') { $valueBuffer[] = $indexid . ":|" . implode('|', $yLabels); @@ -407,6 +376,46 @@ public function getChartUrl($directUrl = true) } } + /** + * Format dates for axis labels + * + * @param string $idx + * @param string $timezoneLocal + * + * @return void + */ + private function formatAxisLabelDate($idx, $timezoneLocal) + { + foreach ($this->_axisLabels[$idx] as $_index => $_label) { + if ($_label != '') { + $period = new \DateTime($_label, new \DateTimeZone($timezoneLocal)); + switch ($this->getDataHelper()->getParam('period')) { + case '24h': + $this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime( + $period->setTime($period->format('H'), 0, 0), + \IntlDateFormatter::NONE, + \IntlDateFormatter::SHORT + ); + break; + case '7d': + case '1m': + $this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime( + $period, + \IntlDateFormatter::SHORT, + \IntlDateFormatter::NONE + ); + break; + case '1y': + case '2y': + $this->_axisLabels[$idx][$_index] = date('m/Y', strtotime($_label)); + break; + } + } else { + $this->_axisLabels[$idx][$_index] = ''; + } + } + } + /** * Get rows data * diff --git a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php index 07af21505f180..8b96dbd09b543 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php @@ -19,8 +19,15 @@ public function testAjaxBlockAction() $this->assertContains('dashboard-diagram', $actual); } + /** + * Tests tunnelAction + * + * @throws \Exception + * @return void + */ public function testTunnelAction() { + // phpcs:disable Magento2.Functions.DiscouragedFunction $testUrl = \Magento\Backend\Block\Dashboard\Graph::API_URL . '?cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World'; $handle = curl_init(); curl_setopt($handle, CURLOPT_URL, $testUrl); @@ -34,6 +41,7 @@ public function testTunnelAction() curl_close($handle); throw $e; } + // phpcs:enable $gaData = [ 'cht' => 'lc', From 0de457220574931d82e11be83b4f565f38ab06cb Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 2 Apr 2019 16:26:53 +0300 Subject: [PATCH 427/603] magento/magento2#21869: Static test fix. --- .../Magento/Eav/Model/Entity/Collection/AbstractCollection.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index 05c6d989fa130..b191f14bb7e60 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -264,7 +264,7 @@ public function setEntity($entity) $this->_entity = $this->_eavEntityFactory->create()->setType($entity); } else { throw new LocalizedException( - __('The "%1" entity supplied is invalid. Verify the entity and try again.', print_r($entity, 1)) + __('The entity supplied to collection is invalid. Verify the entity and try again.') ); } return $this; @@ -1165,7 +1165,6 @@ public function _loadEntities($printQuery = false, $logQuery = false) * @param bool $printQuery * @param bool $logQuery * @return $this - * @throws LocalizedException * @throws \Exception * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) From c0f2c2ad58ab0607a668a8e34f984f0b3f73dcc0 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Tue, 9 Apr 2019 11:15:54 +0300 Subject: [PATCH 428/603] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Added strict type declaration; --- app/code/Magento/Ups/Model/Carrier.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index 9cb1fe615aa42..14b71e5f75db3 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Ups\Model; From 13d1f426de8c64c2059f00a50e02185eed5e0188 Mon Sep 17 00:00:00 2001 From: Davit_Zakharyan <davit_zakharyan@epam.com> Date: Tue, 9 Apr 2019 12:44:11 +0400 Subject: [PATCH 429/603] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Updated automated test script. --- .../Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml b/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml index 9a168f0bd6197..51db704a7abc7 100644 --- a/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml +++ b/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml @@ -31,7 +31,7 @@ <createData entity="ShippingMethodsUpsTypeSetDefault" stepKey="setShippingMethodsUpsTypeToDefault"/> <!-- Navigate to Stores -> Configuration -> Sales -> Shipping Methods Page --> <comment userInput="Navigate to Stores -> Configuration -> Sales -> Shipping Methods Page" stepKey="goToAdminShippingMethodsPage"/> - <amonPage url="{{AdminShippingMethodsConfigPage.url}}" stepKey="navigateToAdminShippingMethodsPage"/> + <amOnPage url="{{AdminShippingMethodsConfigPage.url}}" stepKey="navigateToAdminShippingMethodsPage"/> <waitForPageLoad stepKey="waitPageToLoad"/> <!-- Expand 'UPS' tab --> <comment userInput="Expand UPS tab" stepKey="expandUpsTab"/> From cc4b444f42e281c1899cebb6aafb9c8dd63b38c9 Mon Sep 17 00:00:00 2001 From: Ansari <ziyaurrahman@krishtechnolabs.com> Date: Tue, 9 Apr 2019 14:31:45 +0530 Subject: [PATCH 430/603] Spelling Correction --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b86c7b79a0cbd..9d15fe00b54f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4136,7 +4136,7 @@ Tests: * Moved Multishipping functionality to newly created module Multishipping * Extracted Product duplication behavior from Product model to Product\Copier model * Replaced event "catalog_model_product_duplicate" with composite Product\Copier model - * Replaced event "catalog_product_prepare_save" with controller product initialization helper that can be customozed via plugins + * Replaced event "catalog_product_prepare_save" with controller product initialization helper that can be customized via plugins * Consolidated Authorize.Net functionality in single module Authorizenet * Eliminated dependency of Sales module on Shipping and Usa modules * Eliminated dependency of Shipping module on Customer module From d061c5461a316a44b6cc9b7a48c35aaff98b9719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Me=CC=81ndez=20Calzada?= <gonzalo.mendez@interactiv4.com> Date: Tue, 9 Apr 2019 11:17:42 +0200 Subject: [PATCH 431/603] drop optional unused parameter --- .../Eav/Model/Entity/Attribute/Source/AbstractSource.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php index 0e547e0887c30..b291b7b28d5b7 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php @@ -171,14 +171,11 @@ public function toOptionArray() * Multibyte support strcasecmp function version * @param string $str1 * @param string $str2 - * @param null|string $encoding * @return int|\\lt */ - private function mbStrcasecmp($str1, $str2, $encoding = null) + private function mbStrcasecmp($str1, $str2) { - if (null === $encoding) { - $encoding = mb_internal_encoding(); - } + $encoding = mb_internal_encoding(); return strcmp( mb_strtoupper($str1, $encoding), mb_strtoupper($str2, $encoding) From 07a1570b147ac2cca6bb97e748571304a5ab7b96 Mon Sep 17 00:00:00 2001 From: Evgeny Petrov <evgeny_petrov@epam.com> Date: Tue, 9 Apr 2019 12:42:34 +0300 Subject: [PATCH 432/603] MAGETWO-98584: Google chart API used by Magento dashboard scheduled to be turned off --- app/code/Magento/Backend/Block/Dashboard/Graph.php | 2 ++ .../testsuite/Magento/Backend/Block/Dashboard/GraphTest.php | 2 ++ .../Magento/Backend/Controller/Adminhtml/DashboardTest.php | 2 ++ 3 files changed, 6 insertions(+) diff --git a/app/code/Magento/Backend/Block/Dashboard/Graph.php b/app/code/Magento/Backend/Block/Dashboard/Graph.php index 56e7ab6186ada..f57b03fdbfa0b 100644 --- a/app/code/Magento/Backend/Block/Dashboard/Graph.php +++ b/app/code/Magento/Backend/Block/Dashboard/Graph.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Backend\Block\Dashboard; /** diff --git a/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/GraphTest.php b/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/GraphTest.php index 215fd85d33167..497deb2c99110 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/GraphTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/GraphTest.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Backend\Block\Dashboard; /** diff --git a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php index 8b96dbd09b543..0eb98379b4571 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/DashboardTest.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Backend\Controller\Adminhtml; /** From 4aa6b278e7273066bfceab39dce3f79b4a7085d1 Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Tue, 9 Apr 2019 14:36:37 +0300 Subject: [PATCH 433/603] MC-13479: Persistent Data for Guest Customer with physical quote --- ...tCartEstimateShippingAndTaxActionGroup.xml | 20 +++++ ...tCartShippingMethodSelectedActionGroup.xml | 19 ++++ ...EstimateShippingInformationActionGroup.xml | 20 +++++ ...ckoutShippingMethodSelectedActionGroup.xml | 18 ++++ ...rontAssertGuestShippingInfoActionGroup.xml | 28 ++++++ ...ShippingMethodPresentInCartActionGroup.xml | 18 ++++ ...tCartEstimateShippingAndTaxActionGroup.xml | 25 ++++++ ...efrontFillGuestShippingInfoActionGroup.xml | 25 ++++++ .../Test/Mftf/Data/EstimateAndTaxData.xml | 16 ++++ .../Section/CheckoutCartSummarySection.xml | 3 + .../CheckoutShippingGuestInfoSection.xml | 4 + .../CheckoutShippingMethodsSection.xml | 1 + ...aForGuestCustomerWithPhysicalQuoteTest.xml | 90 +++++++++++++++++++ .../Test/Mftf/Data/NewCustomerData.xml | 26 ++++++ 14 files changed, 313 insertions(+) create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartEstimateShippingAndTaxActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartShippingMethodSelectedActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutEstimateShippingInformationActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutShippingMethodSelectedActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertGuestShippingInfoActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertShippingMethodPresentInCartActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCartEstimateShippingAndTaxActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillGuestShippingInfoActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Data/EstimateAndTaxData.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontPersistentDataForGuestCustomerWithPhysicalQuoteTest.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartEstimateShippingAndTaxActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartEstimateShippingAndTaxActionGroup.xml new file mode 100644 index 0000000000000..0d6f34098c048 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartEstimateShippingAndTaxActionGroup.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 Estimate Shipping and Tax Data in Cart --> + <actionGroup name="StorefrontAssertCartEstimateShippingAndTaxActionGroup"> + <arguments> + <argument name="customerData" defaultValue="Simple_US_CA_Customer_For_Shipment"/> + </arguments> + <seeInField selector="{{CheckoutCartSummarySection.country}}" userInput="{{customerData.country}}" stepKey="assertCountryFieldInCartEstimateShippingAndTaxSection"/> + <seeInField selector="{{CheckoutCartSummarySection.stateProvinceInput}}" userInput="{{customerData.region}}" stepKey="assertStateProvinceInCartEstimateShippingAndTaxSection"/> + <seeInField selector="{{CheckoutCartSummarySection.postcode}}" userInput="{{customerData.postcode}}" stepKey="assertZipPostalCodeInCartEstimateShippingAndTaxSection"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartShippingMethodSelectedActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartShippingMethodSelectedActionGroup.xml new file mode 100644 index 0000000000000..4061f97821cd0 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCartShippingMethodSelectedActionGroup.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 Shipping Method Is Checked on Cart --> + <actionGroup name="StorefrontAssertCartShippingMethodSelectedActionGroup"> + <arguments> + <argument name="carrierCode" type="string"/> + <argument name="methodCode" type="string"/> + </arguments> + <seeCheckboxIsChecked selector="{{CheckoutCartSummarySection.shippingMethodElementId(carrierCode, methodCode)}}" stepKey="assertShippingMethodIsChecked"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutEstimateShippingInformationActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutEstimateShippingInformationActionGroup.xml new file mode 100644 index 0000000000000..82d7e12105b8c --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutEstimateShippingInformationActionGroup.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 Estimate Shipping and Tax Data on Checkout --> + <actionGroup name="StorefrontAssertCheckoutEstimateShippingInformationActionGroup"> + <arguments> + <argument name="customerData" defaultValue="Simple_US_CA_Customer_For_Shipment"/> + </arguments> + <seeInField selector="{{CheckoutShippingGuestInfoSection.country}}" userInput="{{customerData.country}}" stepKey="assertCountryField"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.region}}" userInput="{{customerData.region}}" stepKey="assertStateProvinceField"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.postcode}}" userInput="{{customerData.postcode}}" stepKey="assertZipPostalCodeField"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutShippingMethodSelectedActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutShippingMethodSelectedActionGroup.xml new file mode 100644 index 0000000000000..33f2852f1f0ad --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertCheckoutShippingMethodSelectedActionGroup.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"> + <!-- Assert Shipping Method by Name Is Checked on Checkout --> + <actionGroup name="StorefrontAssertCheckoutShippingMethodSelectedActionGroup"> + <arguments> + <argument name="shippingMethod"/> + </arguments> + <seeCheckboxIsChecked selector="{{CheckoutShippingMethodsSection.checkShippingMethodByName('shippingMethod')}}" stepKey="assertShippingMethodByNameIsChecked"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertGuestShippingInfoActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertGuestShippingInfoActionGroup.xml new file mode 100644 index 0000000000000..02c362bf34058 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertGuestShippingInfoActionGroup.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Assert guest shipping info on checkout --> + <actionGroup name="StorefrontAssertGuestShippingInfoActionGroup"> + <arguments> + <argument name="customerData" defaultValue="Simple_UK_Customer_For_Shipment"/> + </arguments> + <seeInField selector="{{CheckoutShippingGuestInfoSection.email}}" userInput="{{customerData.email}}" stepKey="assertEmailAddress"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.firstName}}" userInput="{{customerData.firstName}}" stepKey="assertFirstName"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.lastName}}" userInput="{{customerData.lastName}}" stepKey="assertLastName"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.company}}" userInput="{{customerData.company}}" stepKey="assertCompany"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.street}}" userInput="{{customerData.streetFirstLine}}" stepKey="assertAddressFirstLine"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.street2}}" userInput="{{customerData.streetSecondLine}}" stepKey="assertAddressSecondLine"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.city}}" userInput="{{customerData.city}}" stepKey="assertCity"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.country}}" userInput="{{customerData.country}}" stepKey="assertCountry"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.regionInput}}" userInput="{{customerData.region}}" stepKey="assertStateProvince"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.postcode}}" userInput="{{customerData.postcode}}" stepKey="assertZipPostalCode"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.telephone}}" userInput="{{customerData.telephone}}" stepKey="assertPhoneNumber"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertShippingMethodPresentInCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertShippingMethodPresentInCartActionGroup.xml new file mode 100644 index 0000000000000..3d8530ae83704 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertShippingMethodPresentInCartActionGroup.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"> + <!-- Assert shipping method is present in cart --> + <actionGroup name="StorefrontAssertShippingMethodPresentInCartActionGroup"> + <arguments> + <argument name="shippingMethod" type="string"/> + </arguments> + <see selector="{{CheckoutCartSummarySection.shippingMethodLabel}}" userInput="{{shippingMethod}}" stepKey="assertShippingMethodIsPresentInCart"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCartEstimateShippingAndTaxActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCartEstimateShippingAndTaxActionGroup.xml new file mode 100644 index 0000000000000..4176859f99f70 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCartEstimateShippingAndTaxActionGroup.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"> + <!-- Fill Estimate Shipping and Tax fields --> + <actionGroup name="StorefrontCartEstimateShippingAndTaxActionGroup"> + <arguments> + <argument name="estimateAddress" defaultValue="EstimateAddressCalifornia"/> + </arguments> + <conditionalClick selector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" dependentSelector="{{CheckoutCartSummarySection.country}}" visible="false" stepKey="clickOnEstimateShippingAndTax"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.country}}" stepKey="waitForCountrySelectorIsVisible"/> + <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="{{estimateAddress.country}}" stepKey="selectCountry"/> + <waitForLoadingMaskToDisappear stepKey="waitForCountryLoadingMaskDisappear"/> + <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="{{estimateAddress.state}}" stepKey="selectStateProvince"/> + <waitForLoadingMaskToDisappear stepKey="waitForStateLoadingMaskDisappear"/> + <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="{{estimateAddress.zipCode}}" stepKey="fillZipPostalCodeField"/> + <waitForLoadingMaskToDisappear stepKey="waitForZipLoadingMaskDisappear"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillGuestShippingInfoActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillGuestShippingInfoActionGroup.xml new file mode 100644 index 0000000000000..e7669d62c79a0 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillGuestShippingInfoActionGroup.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"> + <!-- Fill data in checkout shipping section --> + <actionGroup name="StorefrontFillGuestShippingInfoActionGroup"> + <arguments> + <argument name="customerData" defaultValue="Simple_UK_Customer_For_Shipment"/> + </arguments> + <fillField selector="{{CheckoutShippingGuestInfoSection.email}}" userInput="{{customerData.email}}" stepKey="fillEmailAddressField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.firstName}}" userInput="{{customerData.firstName}}" stepKey="fillFirstNameField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.lastName}}" userInput="{{customerData.lastName}}" stepKey="fillLastNameField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.company}}" userInput="{{customerData.company}}" stepKey="fillCompanyField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.street}}" userInput="{{customerData.streetFirstLine}}" stepKey="fillStreetAddressFirstLineField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.street2}}" userInput="{{customerData.streetSecondLine}}" stepKey="fillStreetAddressSecondLineField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.city}}" userInput="{{customerData.city}}" stepKey="fillCityField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.telephone}}" userInput="{{customerData.telephone}}" stepKey="fillPhoneNumberField"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Data/EstimateAndTaxData.xml b/app/code/Magento/Checkout/Test/Mftf/Data/EstimateAndTaxData.xml new file mode 100644 index 0000000000000..36dea5a521a04 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Data/EstimateAndTaxData.xml @@ -0,0 +1,16 @@ +<?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="EstimateAddressCalifornia"> + <data key="country">United States</data> + <data key="state">California</data> + <data key="zipCode">90240</data> + </entity> +</entities> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml index 8d14a9a561900..3100fae3b119b 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml @@ -20,9 +20,12 @@ <element name="shippingHeading" type="button" selector="#block-shipping-heading"/> <element name="postcode" type="input" selector="input[name='postcode']" timeout="10"/> <element name="stateProvince" type="select" selector="select[name='region_id']" timeout="10"/> + <element name="stateProvinceInput" type="input" selector="input[name='region']"/> <element name="country" type="select" selector="select[name='country_id']" timeout="10"/> <element name="countryParameterized" type="select" selector="select[name='country_id'] > option:nth-child({{var}})" timeout="10" parameterized="true"/> <element name="estimateShippingAndTax" type="text" selector="#block-shipping-heading" timeout="5"/> <element name="flatRateShippingMethod" type="input" selector="#s_method_flatrate_flatrate" timeout="30"/> + <element name="shippingMethodLabel" type="text" selector="#co-shipping-method-form dl dt span"/> + <element name="shippingMethodElementId" type="radio" selector="#s_method_{{carrierCode}}_{{methodCode}}" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml index 6838824400b96..c97a8f291e941 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml @@ -13,9 +13,13 @@ <element name="firstName" type="input" selector="input[name=firstname]"/> <element name="lastName" type="input" selector="input[name=lastname]"/> <element name="street" type="input" selector="input[name='street[0]']"/> + <element name="street2" type="input" selector="input[name='street[1]']"/> <element name="city" type="input" selector="input[name=city]"/> <element name="region" type="select" selector="select[name=region_id]"/> + <element name="regionInput" type="input" selector="input[name=region]"/> <element name="postcode" type="input" selector="input[name=postcode]"/> + <element name="country" type="select" selector="select[name=country_id]"/> + <element name="company" type="input" selector="input[name=company]"/> <element name="telephone" type="input" selector="input[name=telephone]"/> <element name="next" type="button" selector="button.button.action.continue.primary" timeout="30"/> <element name="firstShippingMethod" type="radio" selector=".row:nth-of-type(1) .col-method .radio"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingMethodsSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingMethodsSection.xml index ab4b59fd67d03..77d903eab3934 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingMethodsSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingMethodsSection.xml @@ -17,5 +17,6 @@ <element name="shippingMethodRowByName" type="text" selector="//div[@id='checkout-shipping-method-load']//td[contains(., '{{var1}}')]/.." parameterized="true"/> <element name="shipHereButton" type="button" selector="//div/following-sibling::div/button[contains(@class, 'action-select-shipping-item')]"/> <element name="shippingMethodLoader" type="button" selector="//div[contains(@class, 'checkout-shipping-method')]/following-sibling::div[contains(@class, 'loading-mask')]"/> + <element name="freeShippingShippingMethod" type="input" selector="#s_method_freeshipping_freeshipping" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontPersistentDataForGuestCustomerWithPhysicalQuoteTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontPersistentDataForGuestCustomerWithPhysicalQuoteTest.xml new file mode 100644 index 0000000000000..20ff67a076e1e --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontPersistentDataForGuestCustomerWithPhysicalQuoteTest.xml @@ -0,0 +1,90 @@ +<?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="StorefrontPersistentDataForGuestCustomerWithPhysicalQuoteTest"> + <annotations> + <features value="Checkout"/> + <stories value="Checkout via Guest Checkout"/> + <title value="Persistent Data for Guest Customer with physical quote"/> + <description value="One can use Persistent Data for Guest Customer with physical quote"/> + <severity value="MAJOR"/> + <testCaseId value="MC-13479"/> + <group value="checkout"/> + </annotations> + <before> + <createData entity="SimpleProduct2" stepKey="createProduct"> + <field key="price">10</field> + </createData> + <createData entity="FreeShippinMethodConfig" stepKey="enableFreeShipping"/> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefront"/> + <executeJS function="window.localStorage.clear();" stepKey="clearLocalStorage"/> + </before> + <after> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <createData entity="FreeShippinMethodDefault" stepKey="disableFreeShipping"/> + </after> + <!-- 1. Add simple product to cart and go to checkout--> + <actionGroup ref="AddSimpleProductToCart" stepKey="addSimpleProductToCart"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> + <!-- 2. Go to Shopping Cart --> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCheckoutCartIndexPage"/> + <!-- 3. Open "Estimate Shipping and Tax" section and input data --> + <actionGroup ref="StorefrontCartEstimateShippingAndTaxActionGroup" stepKey="fillEstimateShippingAndTaxSection"/> + <actionGroup ref="StorefrontAssertShippingMethodPresentInCartActionGroup" stepKey="assertShippingMethodFlatRateIsPresentInCart"> + <argument name="shippingMethod" value="Flat Rate"/> + </actionGroup> + <actionGroup ref="StorefrontAssertShippingMethodPresentInCartActionGroup" stepKey="assertShippingMethodFreeShippingIsPresentInCart"> + <argument name="shippingMethod" value="Free Shipping"/> + </actionGroup> + <!-- 4. Select Flat Rate as shipping --> + <checkOption selector="{{CheckoutCartSummarySection.flatRateShippingMethod}}" stepKey="selectFlatRateShippingMethod"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappearAfterFlatRateSelection"/> + <see selector="{{CheckoutCartSummarySection.total}}" userInput="15" stepKey="assertOrderTotalField"/> + <!-- 5. Refresh browser page (F5) --> + <reloadPage stepKey="reloadPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <actionGroup ref="StorefrontAssertCartEstimateShippingAndTaxActionGroup" stepKey="assertCartEstimateShippingAndTaxAfterPageReload"/> + <actionGroup ref="StorefrontAssertCartShippingMethodSelectedActionGroup" stepKey="assertFlatRateShippingMethodIsChecked"> + <argument name="carrierCode" value="flatrate"/> + <argument name="methodCode" value="flatrate"/> + </actionGroup> + <!-- 6. Go to Checkout --> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="clickProceedToCheckout"/> + <actionGroup ref="StorefrontAssertCheckoutEstimateShippingInformationActionGroup" stepKey="assertCheckoutEstimateShippingInformationAfterGoingToCheckout"/> + <actionGroup ref="StorefrontAssertCheckoutShippingMethodSelectedActionGroup" stepKey="assertFlatRateShippingMethodIsCheckedAfterGoingToCheckout"> + <argument name="shippingMethod" value="Flat Rate"/> + </actionGroup> + <!-- 7. Change persisted data --> + <selectOption selector="{{CheckoutShippingGuestInfoSection.country}}" userInput="United Kingdom" stepKey="changeCountryField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.regionInput}}" userInput="" stepKey="changeStateProvinceField"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.postcode}}" userInput="KW1 7NQ" stepKey="changeZipPostalCodeField"/> + <!-- 8. Change shipping rate, select Free Shipping --> + <checkOption selector="{{CheckoutShippingMethodsSection.checkShippingMethodByName('Free Shipping')}}" stepKey="checkFreeShippingAsShippingMethod"/> + <!-- 9. Fill other fields --> + <actionGroup ref="StorefrontFillGuestShippingInfoActionGroup" stepKey="fillOtherFieldsInCheckoutShippingSection"/> + <!-- 10. Refresh browser page(F5) --> + <reloadPage stepKey="reloadCheckoutPage"/> + <waitForPageLoad stepKey="waitForCheckoutPageLoad"/> + <actionGroup ref="StorefrontAssertGuestShippingInfoActionGroup" stepKey="assertGuestShippingPersistedInfoAfterReloadingCheckoutShippingPage"/> + <actionGroup ref="StorefrontAssertCheckoutShippingMethodSelectedActionGroup" stepKey="assertFreeShippingShippingMethodIsChecked"> + <argument name="shippingMethod" value="Free Shipping"/> + </actionGroup> + <!-- 11. Go back to the shopping cart --> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCheckoutCartIndexPage1"/> + <actionGroup ref="StorefrontAssertCartEstimateShippingAndTaxActionGroup" stepKey="assertCartEstimateShippingAndTaxAfterGoingBackToShoppingCart"> + <argument name="customerData" value="Simple_UK_Customer_For_Shipment"/> + </actionGroup> + <actionGroup ref="StorefrontAssertCartShippingMethodSelectedActionGroup" stepKey="assertFreeShippingShippingMethodIsCheckedAfterGoingBackToShoppingCart"> + <argument name="carrierCode" value="freeshipping"/> + <argument name="methodCode" value="freeshipping"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/NewCustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/NewCustomerData.xml index cdd117c2a0b12..347a04251f9cd 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/NewCustomerData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/NewCustomerData.xml @@ -20,4 +20,30 @@ <data key="PhoneNumber">9999</data> <data key="Country">Armenia</data> </entity> + <entity name="Simple_UK_Customer_For_Shipment" type="customer"> + <data key="firstName">John</data> + <data key="lastName">Doe</data> + <data key="email">johndoe@example.com</data> + <data key="company">Test Company</data> + <data key="streetFirstLine">39 St Maurices Road</data> + <data key="streetSecondLine">ap. 654</data> + <data key="city">PULDAGON</data> + <data key="telephone">077 5866 0667</data> + <data key="country">United Kingdom</data> + <data key="region"> </data> + <data key="postcode">KW1 7NQ</data> + </entity> + <entity name="Simple_US_CA_Customer_For_Shipment" type="customer"> + <data key="firstName">John</data> + <data key="lastName">Doe</data> + <data key="email">johndoeusca@example.com</data> + <data key="company">Magento</data> + <data key="streetFirstLine">123 Alphabet Drive</data> + <data key="streetSecondLine">ap. 350</data> + <data key="city">Los Angeles</data> + <data key="telephone">555-55-555-55</data> + <data key="country">United States</data> + <data key="region">California</data> + <data key="postcode">90240</data> + </entity> </entities> From cc5c711b316c072d72a7174dbd8bb2dff03b67a0 Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Tue, 9 Apr 2019 17:41:54 +0530 Subject: [PATCH 434/603] Fixed wrong url redirect when edit product review from product view page (type casting to int) --- app/code/Magento/Review/Controller/Adminhtml/Product/Save.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php b/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php index 9c85ae7db22d9..57b1e538ddb6b 100644 --- a/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php +++ b/app/code/Magento/Review/Controller/Adminhtml/Product/Save.php @@ -73,7 +73,7 @@ public function execute() } else { $resultRedirect->setPath('*/*/'); } - $productId = $this->getRequest()->getParam('productId'); + $productId = (int)$this->getRequest()->getParam('productId'); if ($productId) { $resultRedirect->setPath("catalog/product/edit/id/$productId"); } From b159dfb6004281991de5ee3f80936d69e65fe5ed Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 9 Apr 2019 15:54:38 +0300 Subject: [PATCH 435/603] magento/magento2#20772: MTF test fix. --- .../AssertAccessTokensErrorRevokeMessage.php | 46 ------------------- .../AssertAccessTokensSuccessfullyRevoked.php | 45 ++++++++++++++++++ ...lAccessTokensForAdminWithoutTokensTest.xml | 2 +- 3 files changed, 46 insertions(+), 47 deletions(-) delete mode 100644 dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensErrorRevokeMessage.php create mode 100644 dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensSuccessfullyRevoked.php diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensErrorRevokeMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensErrorRevokeMessage.php deleted file mode 100644 index b1a64c7c7e713..0000000000000 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensErrorRevokeMessage.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\User\Test\Constraint; - -use Magento\User\Test\Page\Adminhtml\UserEdit; -use Magento\Mtf\Constraint\AbstractConstraint; - -/** - * Class AssertAccessTokensErrorRevokeMessage - * Assert that error message appears after click on 'Force Sing-In' button for user without tokens. - */ -class AssertAccessTokensErrorRevokeMessage extends AbstractConstraint -{ - /** - * User revoke tokens error message. - */ - const ERROR_MESSAGE = 'This user has no tokens.'; - - /** - * Assert that error message appears after click on 'Force Sing-In' button for user without tokens. - * - * @param UserEdit $userEdit - * @return void - */ - public function processAssert(UserEdit $userEdit) - { - \PHPUnit\Framework\Assert::assertEquals( - self::ERROR_MESSAGE, - $userEdit->getMessagesBlock()->getErrorMessage() - ); - } - - /** - * Return string representation of object - * - * @return string - */ - public function toString() - { - return self::ERROR_MESSAGE . ' error message is present on UserEdit page.'; - } -} diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensSuccessfullyRevoked.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensSuccessfullyRevoked.php new file mode 100644 index 0000000000000..b2e52f6a15a10 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensSuccessfullyRevoked.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\User\Test\Constraint; + +use Magento\User\Test\Page\Adminhtml\UserEdit; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Assert that success message appears after click on 'Force Sing-In' button. + */ +class AssertAccessTokensSuccessfullyRevoked extends AbstractConstraint +{ + /** + * User revoke tokens success message. + */ + const SUCCESS_MESSAGE = 'You have revoked the user\'s tokens.'; + + /** + * Assert that success message appears after click on 'Force Sing-In' button. + * + * @param UserEdit $userEdit + * @return void + */ + public function processAssert(UserEdit $userEdit): void + { + \PHPUnit\Framework\Assert::assertEquals( + self::SUCCESS_MESSAGE, + $userEdit->getMessagesBlock()->getSuccessMessage() + ); + } + + /** + * Return string representation of object + * + * @return string + */ + public function toString() + { + return self::SUCCESS_MESSAGE . ' message is present on UserEdit page.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/RevokeAllAccessTokensForAdminWithoutTokensTest.xml b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/RevokeAllAccessTokensForAdminWithoutTokensTest.xml index e5fcba9b72c25..afdb72d8c561e 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/RevokeAllAccessTokensForAdminWithoutTokensTest.xml +++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/RevokeAllAccessTokensForAdminWithoutTokensTest.xml @@ -9,7 +9,7 @@ <testCase name="Magento\User\Test\TestCase\RevokeAllAccessTokensForAdminWithoutTokensTest" summary="Revoke All Access Tokens for Admin without Tokens" ticketId="MAGETWO-29675"> <variation name="RevokeAllAccessTokensForAdminWithoutTokensTestVariation1"> <data name="user/dataset" xsi:type="string">custom_admin</data> - <constraint name="Magento\User\Test\Constraint\AssertAccessTokensErrorRevokeMessage" /> + <constraint name="Magento\User\Test\Constraint\AssertAccessTokensSuccessfullyRevoked" /> </variation> </testCase> </config> From 8d114560f9ed103cfea3f0712419f8bb698ed20a Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Tue, 9 Apr 2019 08:14:33 -0500 Subject: [PATCH 436/603] MAGETWO-99091: Name of categories in the Category tree on Product Edit page is not displayed according to the selected store view scope --- .../Product/Form/Modifier/CategoriesTest.php | 34 -------- .../Product/Form/Modifier/Categories.php | 78 +++++++++++++++---- 2 files changed, 64 insertions(+), 48 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php index cd6565f32ed18..a2d81854607a0 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php @@ -154,38 +154,4 @@ public function modifyMetaLockedDataProvider() { return [[true], [false]]; } - - public function testModifyMetaWithCaching() - { - $this->arrayManagerMock->expects($this->exactly(2)) - ->method('findPath') - ->willReturn(true); - $cacheManager = $this->getMockBuilder(CacheInterface::class) - ->getMockForAbstractClass(); - $cacheManager->expects($this->once()) - ->method('load') - ->with(Categories::CATEGORY_TREE_ID . '_'); - $cacheManager->expects($this->once()) - ->method('save'); - - $modifier = $this->createModel(); - $cacheContextProperty = new \ReflectionProperty( - Categories::class, - 'cacheManager' - ); - $cacheContextProperty->setAccessible(true); - $cacheContextProperty->setValue($modifier, $cacheManager); - - $groupCode = 'test_group_code'; - $meta = [ - $groupCode => [ - 'children' => [ - 'category_ids' => [ - 'sortOrder' => 10, - ], - ], - ], - ]; - $modifier->modifyMeta($meta); - } } diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php index 681435851fbde..8dc4b8100345e 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php @@ -11,6 +11,7 @@ use Magento\Framework\App\CacheInterface; use Magento\Framework\DB\Helper as DbHelper; use Magento\Catalog\Model\Category as CategoryModel; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\UrlInterface; use Magento\Framework\Stdlib\ArrayManager; @@ -202,6 +203,7 @@ protected function createNewCategoryModal(array $meta) * * @param array $meta * @return array + * @throws LocalizedException * @since 101.0.0 */ protected function customizeCategoriesField(array $meta) @@ -306,20 +308,64 @@ protected function customizeCategoriesField(array $meta) * * @param string|null $filter * @return array + * @throws LocalizedException * @since 101.0.0 */ protected function getCategoriesTree($filter = null) { - $categoryTree = $this->getCacheManager()->load(self::CATEGORY_TREE_ID . '_' . $filter); - if ($categoryTree) { - return $this->serializer->unserialize($categoryTree); + $storeId = $this->locator->getStore()->getId(); + + $cachedCategoriesTree = $this->getCacheManager() + ->load($this->getCategoriesTreeCacheId($storeId, (string) $filter)); + if (!empty($cachedCategoriesTree)) { + return $this->serializer->unserialize($cachedCategoriesTree); } - $storeId = $this->locator->getStore()->getId(); + $categoriesTree = $this->retrieveCategoriesTree( + $storeId, + $this->retrieveShownCategoriesIds($storeId, (string) $filter) + ); + + $this->getCacheManager()->save( + $this->serializer->serialize($categoriesTree), + $this->getCategoriesTreeCacheId($storeId, (string) $filter), + [ + \Magento\Catalog\Model\Category::CACHE_TAG, + \Magento\Framework\App\Cache\Type\Block::CACHE_TAG + ] + ); + + return $categoriesTree; + } + + /** + * Get cache id for categories tree. + * + * @param int $storeId + * @param string $filter + * @return string + */ + private function getCategoriesTreeCacheId($storeId, $filter = '') + { + return self::CATEGORY_TREE_ID + . '_' . (string) $storeId + . '_' . $filter; + } + + /** + * Retrieve filtered list of categories id. + * + * @param int $storeId + * @param string $filter + * @return array + * @throws LocalizedException + */ + private function retrieveShownCategoriesIds($storeId, $filter = '') + { /* @var $matchingNamesCollection \Magento\Catalog\Model\ResourceModel\Category\Collection */ $matchingNamesCollection = $this->categoryCollectionFactory->create(); - if ($filter !== null) { + if (!empty($filter)) { $matchingNamesCollection->addAttributeToFilter( 'name', ['like' => $this->dbHelper->addLikeEscape($filter, ['position' => 'any'])] @@ -339,6 +385,19 @@ protected function getCategoriesTree($filter = null) } } + return $shownCategoriesIds; + } + + /** + * Retrieve tree of categories with attributes. + * + * @param int $storeId + * @param array $shownCategoriesIds + * @return array + * @throws LocalizedException + */ + private function retrieveCategoriesTree($storeId, array $shownCategoriesIds = []) + { /* @var $collection \Magento\Catalog\Model\ResourceModel\Category\Collection */ $collection = $this->categoryCollectionFactory->create(); @@ -365,15 +424,6 @@ protected function getCategoriesTree($filter = null) $categoryById[$category->getParentId()]['optgroup'][] = &$categoryById[$category->getId()]; } - $this->getCacheManager()->save( - $this->serializer->serialize($categoryById[CategoryModel::TREE_ROOT_ID]['optgroup']), - self::CATEGORY_TREE_ID . '_' . $filter, - [ - \Magento\Catalog\Model\Category::CACHE_TAG, - \Magento\Framework\App\Cache\Type\Block::CACHE_TAG - ] - ); - return $categoryById[CategoryModel::TREE_ROOT_ID]['optgroup']; } } From 4921f459324328f9b04916f1722e762f98466f5c Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Tue, 9 Apr 2019 09:05:50 -0500 Subject: [PATCH 437/603] MAGETWO-93628: Shopping cart is emptied after reset password procedure --- app/code/Magento/Customer/Model/AccountManagement.php | 6 +++++- .../Customer/Test/Unit/Model/AccountManagementTest.php | 4 +--- lib/internal/Magento/Framework/Session/SessionManager.php | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 0440eb161e9e0..1806ea05f2fea 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -702,7 +702,11 @@ public function resetPassword($email, $resetToken, $newPassword) $customerSecure->setRpTokenCreatedAt(null); $customerSecure->setPasswordHash($this->createPasswordHash($newPassword)); $this->destroyCustomerSessions($customer->getId()); - $this->sessionManager->destroy(['send_expire_cookie' => false]); + if ($this->sessionManager->isSessionExists()) { + //delete old session and move data to the new session + //use this instead of $this->sessionManager->regenerateId because last one doesn't delete old session + session_regenerate_id(true); + } $this->customerRepository->save($customer); return true; diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 24a96a929a067..209a9b077a307 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -1607,9 +1607,7 @@ function ($string) { $this->customerSecure->expects($this->once())->method('setRpTokenCreatedAt')->with(null); $this->customerSecure->expects($this->any())->method('setPasswordHash')->willReturn(null); - $this->sessionManager->expects($this->once()) - ->method('destroy') - ->with(['send_expire_cookie' => false]); + $this->sessionManager->method('isSessionExists')->willReturn(false); $this->sessionManager->expects($this->atLeastOnce())->method('getSessionId'); $visitor = $this->getMockBuilder(\Magento\Customer\Model\Visitor::class) ->disableOriginalConstructor() diff --git a/lib/internal/Magento/Framework/Session/SessionManager.php b/lib/internal/Magento/Framework/Session/SessionManager.php index b306b879b7127..c7d201676b228 100644 --- a/lib/internal/Magento/Framework/Session/SessionManager.php +++ b/lib/internal/Magento/Framework/Session/SessionManager.php @@ -353,6 +353,7 @@ public function destroy(array $options = null) } session_regenerate_id(true); + session_destroy(); if ($options['send_expire_cookie']) { $this->expireSessionCookie(); } From 52f6df2a7e73503f0eebd7898f6bc6f80dee78c4 Mon Sep 17 00:00:00 2001 From: dimonovp <dimonovp@gmail.com> Date: Tue, 9 Apr 2019 17:37:53 +0300 Subject: [PATCH 438/603] MC-12180: Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie --- .../CatalogRecentlyProductsConfigData.xml | 25 +++ .../catalog_recently_products-meta.xml | 20 +++ ...listIsPersistedUnderLongTermCookieTest.xml | 169 ++++++++++++++++++ .../AdminCreateWidgetActionGroup.xml | 6 + .../Widget/Test/Mftf/Data/WidgetsData.xml | 20 +++ .../Mftf/Section/AdminNewWidgetSection.xml | 2 + .../Mftf/Section/StorefrontWidgetsSection.xml | 3 + 7 files changed, 245 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/Data/CatalogRecentlyProductsConfigData.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml create mode 100644 app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/CatalogRecentlyProductsConfigData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/CatalogRecentlyProductsConfigData.xml new file mode 100644 index 0000000000000..d1e469deaebba --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Data/CatalogRecentlyProductsConfigData.xml @@ -0,0 +1,25 @@ +<?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="EnableSynchronizeWidgetProductsWithBackendStorage" type="catalog_recently_products"> + <requiredEntity type="synchronize_with_backend">EnableCatalogRecentlyProductsSynchronize</requiredEntity> + </entity> + + <entity name="EnableCatalogRecentlyProductsSynchronize" type="synchronize_with_backend"> + <data key="value">1</data> + </entity> + + <entity name="DisableSynchronizeWidgetProductsWithBackendStorage" type="catalog_recently_products"> + <requiredEntity type="synchronize_with_backend">DefaultCatalogRecentlyProductsSynchronize</requiredEntity> + </entity> + + <entity name="DefaultCatalogRecentlyProductsSynchronize" type="synchronize_with_backend"> + <data key="value">0</data> + </entity> +</entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml b/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml new file mode 100644 index 0000000000000..dad4f5420d461 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml @@ -0,0 +1,20 @@ +<?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="CatalogRecentlyProductsConfiguration" dataType="catalog_recently_products" type="create" auth="adminFormKey" url="/admin/system_config/save/section/catalog/" method="POST"> + <object key="groups" dataType="catalog_recently_products"> + <object key="recently_products" dataType="catalog_recently_products"> + <object key="fields" dataType="catalog_recently_products"> + <object key="synchronize_with_backend" dataType="synchronize_with_backend"> + <field key="value">integer</field> + </object> + </object> + </object> + </object> + </operation> +</operations> diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml new file mode 100644 index 0000000000000..b47c5f9571931 --- /dev/null +++ b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml @@ -0,0 +1,169 @@ +<?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="StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest"> + <annotations> + <features value="Persistent"/> + <stories value="Check the widgets is persisted"/> + <title value="Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie"/> + <description value="Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-12180"/> + <group value="persistent"/> + <skip> + <issueId value="MC-15741"/> + </skip> + </annotations> + <before> + <createData entity="PersistentConfigEnabled" stepKey="enablePersistent"/> + <createData entity="PersistentLogoutClearDisable" stepKey="persistentLogoutClearDisable"/> + <createData entity="EnableSynchronizeWidgetProductsWithBackendStorage" stepKey="enableSynchronizeWidgetProductsWithBackendStorage"/> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="_defaultProduct" stepKey="createSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="SimpleProduct" stepKey="createSimpleProduct2"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + + <actionGroup ref="LoginAsAdmin" stepKey="login"/> + <actionGroup ref="AdminCreateRecentlyProductsWidgetActionGroup" stepKey="createRecentlyComparedProductsWidget"> + <argument name="widget" value="RecentlyComparedProductsWidget"/> + </actionGroup> + <actionGroup ref="AdminCreateRecentlyProductsWidgetActionGroup" stepKey="createRecentlyViewedProductsWidget"> + <argument name="widget" value="RecentlyViewedProductsWidget"/> + </actionGroup> + </before> + <after> + <createData entity="PersistentConfigDefault" stepKey="setDefaultPersistentState"/> + <createData entity="PersistentLogoutClearEnabled" stepKey="persistentLogoutClearEnabled"/> + <createData entity="DisableSynchronizeWidgetProductsWithBackendStorage" stepKey="disableSynchronizeWidgetProductsWithBackendStorage"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="createSimpleProduct2" stepKey="deleteSimpleProduct2"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutFromCustomer"/> + <actionGroup ref="AdminDeleteWidgetActionGroup" stepKey="deleteRecentlyComparedProductsWidget"> + <argument name="widget" value="RecentlyComparedProductsWidget"/> + </actionGroup> + <actionGroup ref="AdminDeleteWidgetActionGroup" stepKey="deleteRecentlyViewedProductsWidget"> + <argument name="widget" value="RecentlyViewedProductsWidget"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Login to storefront from customer--> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="logInFromCustomer"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome"/> + + <!--Open the details page of Simple Product 1, Simple Product 2 and add to cart, get to the category--> + <actionGroup ref="AddSimpleProductToCart" stepKey="addProductToCart"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="AddSimpleProductToCart" stepKey="addProductToCart2"> + <argument name="product" value="$$createSimpleProduct2$$"/> + </actionGroup> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage3"/> + <!--The Recently Viewed widget displays Simple Product 1 and Simple Product 2--> + <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" stepKey="waitWidgetRecentlyViewedProductsGrid"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct1InRecentlyViewedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct2.name$$" stepKey="seeProduct2InRecentlyViewedWidget"/> + + <!--Add Simple Product 1 and Simple Product 2 to Wishlist--> + <actionGroup ref="StorefrontCustomerAddCategoryProductToWishlistActionGroup" stepKey="addSimpleProduct1ToWishlist"> + <argument name="productVar" value="$$createSimpleProduct$$"/> + </actionGroup> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage4"/> + <actionGroup ref="StorefrontCustomerAddCategoryProductToWishlistActionGroup" stepKey="addSimpleProduct2ToWishlist"> + <argument name="productVar" value="$$createSimpleProduct2$$"/> + </actionGroup> + <!--The My Wishlist widget displays Simple Product 1 and Simple Product 2--> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage5"/> + <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProductInWishlistSidebar"> + <argument name="productVar" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProduct2InWishlistSidebar"> + <argument name="productVar" value="$$createSimpleProduct2$$"/> + </actionGroup> + + <!--Add to compare Simple Product and Simple Product 2--> + <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="compareAddSimpleProduct1ToCompare" > + <argument name="productVar" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="compareAddSimpleProduct2ToCompare" > + <argument name="productVar" value="$$createSimpleProduct2$$"/> + </actionGroup> + <!--The Compare Products widget displays Simple Product 1 and Simple Product 2--> + <actionGroup ref="StorefrontCheckCompareSidebarProductActionGroup" stepKey="compareSimpleProduct1InSidebar"> + <argument name="productVar" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckCompareSidebarProductActionGroup" stepKey="compareSimpleProduct2InSidebar"> + <argument name="productVar" value="$$createSimpleProduct2$$"/> + </actionGroup> + + <!--Click Clear all in the Compare Products widget--> + <waitForElementVisible selector="{{WidgetSection.ClearCompare}}" stepKey="waitForClearCompareBtn"/> + <click selector="{{WidgetSection.ClearCompare}}" stepKey="clickClearCompareBtn"/> + <waitForElementVisible selector="{{WidgetSection.AcceptClear}}" stepKey="waitForAcceptBtn"/> + <click selector="{{WidgetSection.AcceptClear}}" stepKey="acceptClearCompare"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <!--The Recently Compared widget displays Simple Product 1 and Simple Product 2--> + <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" stepKey="waitWidgetRecentlyComparedProductsGrid"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyComparedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct2InRecentlyComparedWidget"/> + + <!--Place the order--> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToShoppingCartPage"/> + <actionGroup ref="PlaceOrderWithLoggedUserActionGroup" stepKey="placeOrder"> + <argument name="shippingMethod" value="Flat Rate"/> + </actionGroup> + <!--The Recently Ordered widget displays Simple Product 1 and Simple Product 2--> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage6"/> + <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" stepKey="waitWidgetRecentlyOrderedProductsGrid"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyOrderedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct2InRecentlyOrderedWidget"/> + + <!--Sign out and check that widgets persist the information about the items--> + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="storefrontSignOut"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage7"/> + <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome2"/> + <seeElement selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="checkLinkNotYoy"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct1InRecentlyViewedWidget2"/> + <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProductInWishlistSidebar2"> + <argument name="productVar" value="$$createSimpleProduct$$"/> + </actionGroup> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyComparedWidget2"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyOrderedWidget2"/> + + <!--Click the *Not you?* link and check the price for Simple Product--> + <click selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="clickNext"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage8"/> + <see userInput="Default welcome msg!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome3"/> + <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProduct1InRecentlyViewedWidget"/> + <dontSee selector="{{StorefrontCustomerWishlistSidebarSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="dontSeeProduct1InWishlistWidget"/> + <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProductInRecentlyComparedWidget"/> + <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProductInRecentlyOrderedWidget"/> + + <!--Login to storefront from customer again--> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="logInFromCustomer2"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage9"/> + <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome4"/> + <waitForElementVisible selector="{{StorefrontCustomerWishlistSidebarSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="assertWishlistSidebarProductName"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct1InRecentlyViewedWidget3"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyComparedWidget3"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyOrderedWidget3"/> + </test> +</tests> diff --git a/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml b/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml index 969ab58b04876..5d2b894b86438 100644 --- a/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml +++ b/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml @@ -78,4 +78,10 @@ <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveWidget"/> <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been saved" stepKey="seeSuccess"/> </actionGroup> + <actionGroup name="AdminCreateRecentlyProductsWidgetActionGroup" extends="AdminCreateWidgetActionGroup"> + <selectOption selector="{{AdminNewWidgetSection.productAttributesToShow}}" parameterArray="['Name', 'Image', 'Price']" stepKey="selectAllProductAttributes"/> + <selectOption selector="{{AdminNewWidgetSection.productButtonsToShow}}" parameterArray="['Add to Cart', 'Add to Compare', 'Add to Wishlist']" stepKey="selectAllProductButtons"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveWidget"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been saved" stepKey="seeSuccess"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml b/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml index 27222298408de..370077f6feefa 100644 --- a/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml +++ b/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml @@ -32,4 +32,24 @@ <data key="display_mode">Cart Price Rule Related</data> <data key="restrict_type">Header</data> </entity> + <entity name="RecentlyComparedProductsWidget" type="widget"> + <data key="type">Recently Compared Products</data> + <data key="design_theme">Magento Luma</data> + <data key="name" unique="suffix">Recently Compared Products</data> + <array key="store_ids"> + <item>All Store Views</item> + </array> + <data key="display_on">All Pages</data> + <data key="container">Sidebar Additional</data> + </entity> + <entity name="RecentlyViewedProductsWidget" type="widget"> + <data key="type">Recently Viewed Products</data> + <data key="design_theme">Magento Luma</data> + <data key="name" unique="suffix">Recently Viewed Products</data> + <array key="store_ids"> + <item>All Store Views</item> + </array> + <data key="display_on">All Pages</data> + <data key="container">Sidebar Additional</data> + </entity> </entities> diff --git a/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml b/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml index eebd6c10b5085..8abd8cb142016 100644 --- a/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml +++ b/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml @@ -35,5 +35,7 @@ <element name="displayMode" type="select" selector="select[id*='display_mode']"/> <element name="restrictTypes" type="select" selector="select[id*='types']"/> <element name="saveAndContinue" type="button" selector="#save_and_edit_button" timeout="30"/> + <element name="productAttributesToShow" type="multiselect" selector="select[name='parameters[show_attributes][]']"/> + <element name="productButtonsToShow" type="multiselect" selector="select[name='parameters[show_buttons][]']"/> </section> </sections> diff --git a/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml b/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml index 0e2f6cec73a92..cf6bfc484cc57 100644 --- a/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml +++ b/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml @@ -11,5 +11,8 @@ <section name="StorefrontWidgetsSection"> <element name="widgetProductsGrid" type="block" selector=".block.widget.block-products-list.grid"/> <element name="widgetProductName" type="text" selector=".product-item-name"/> + <element name="widgetRecentlyViewedProductsGrid" type="block" selector=".block.widget.block-viewed-products-grid" timeout="30"/> + <element name="widgetRecentlyComparedProductsGrid" type="block" selector=".block.widget.block-compared-products-grid" timeout="30"/> + <element name="widgetRecentlyOrderedProductsGrid" type="block" selector=".block.block-reorder" timeout="30"/> </section> </sections> From 4b44e4a3f21e1b484e661e9de66dab7afa5e4bf7 Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Tue, 9 Apr 2019 09:45:03 -0500 Subject: [PATCH 439/603] MC-15734: Create new GraphQL script for our benchmark - part 2 --- setup/performance-toolkit/benchmark.jmx | 474 +++++++++++++++++++++++- 1 file changed, 470 insertions(+), 4 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 2035da9d58265..31ccf845a625d 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -39866,13 +39866,13 @@ vars.putObject("randomIntGenerator", random); </BeanShellSampler> <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> <stringProp name="BeanShellSampler.query"> import java.util.Random; Random random = vars.getObject("randomIntGenerator"); -number = random.nextInt(props.get("simple_products_list").size()); -product = props.get("simple_products_list").get(number); +number = random.nextInt(props.get("configurable_products_list").size()); +product = props.get("configurable_products_list").get(number); vars.put("product_url_key", product.get("url_key")); vars.put("product_id", product.get("id")); @@ -39883,7 +39883,7 @@ vars.put("product_sku", product.get("sku")); <stringProp name="BeanShellSampler.filename"/> <stringProp name="BeanShellSampler.parameters"/> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> <hashTree/> <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Product Search by product_name" enabled="true"> @@ -40782,6 +40782,239 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product qty In Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/update_simple_product_qty_in_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Billing Address On Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_billing_address_on_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1147076914">{"data":{"setBillingAddressOnCart":{"cart":{"billing_address":{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"BILLING"}}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Shipping Address On Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n setShippingAddressesOnCart(\n input: {\n cart_id: \"${quote_id}\"\n shipping_addresses: [\n {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n ]\n }\n ) {\n cart {\n shipping_addresses {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_shipping_address_on_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1671866339">{"data":{"setShippingAddressesOnCart":{"cart":{"shipping_addresses":[{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"SHIPPING"}]}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Payment Method On Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n setPaymentMethodOnCart(input: {\n cart_id: \"${quote_id}\", \n payment_method: {\n code: \"checkmo\"\n }\n }) {\n cart {\n selected_payment_method {\n code\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_payment_method_on_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1830199373">{"data":{"setPaymentMethodOnCart":{"cart":{"selected_payment_method":{"code":"checkmo"}}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Current Shipping Address" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n shipping_addresses {\n address_id\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_current_shipping_address.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">address_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.shipping_addresses[0].address_id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Shipping Method On Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n setShippingMethodsOnCart(input: \n {\n cart_id: \"${quote_id}\", \n shipping_methods: [{\n cart_address_id: ${address_id}\n carrier_code: \"flatrate\"\n method_code: \"flatrate\"\n }]\n }) {\n cart {\n shipping_addresses {\n selected_shipping_method {\n carrier_code\n method_code\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_shipping_method_on_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="644143859">{"data":{"setShippingMethodsOnCart":{"cart":{"shipping_addresses":[{"selected_shipping_method":{"carrier_code":"flatrate","method_code":"flatrate"}}]}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Simple Product From Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> @@ -41070,6 +41303,239 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product qty In Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/update_configurable_product_qty_in_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Billing Address On Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_billing_address_on_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1147076914">{"data":{"setBillingAddressOnCart":{"cart":{"billing_address":{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"BILLING"}}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Shipping Address On Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n setShippingAddressesOnCart(\n input: {\n cart_id: \"${quote_id}\"\n shipping_addresses: [\n {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n ]\n }\n ) {\n cart {\n shipping_addresses {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_shipping_address_on_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1671866339">{"data":{"setShippingAddressesOnCart":{"cart":{"shipping_addresses":[{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"SHIPPING"}]}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Payment Method On Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n setPaymentMethodOnCart(input: {\n cart_id: \"${quote_id}\", \n payment_method: {\n code: \"checkmo\"\n }\n }) {\n cart {\n selected_payment_method {\n code\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_payment_method_on_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1830199373">{"data":{"setPaymentMethodOnCart":{"cart":{"selected_payment_method":{"code":"checkmo"}}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Current Shipping Address" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n shipping_addresses {\n address_id\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_current_shipping_address.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">address_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.shipping_addresses[0].address_id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Shipping Method On Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n setShippingMethodsOnCart(input: \n {\n cart_id: \"${quote_id}\", \n shipping_methods: [{\n cart_address_id: ${address_id}\n carrier_code: \"flatrate\"\n method_code: \"flatrate\"\n }]\n }) {\n cart {\n shipping_addresses {\n selected_shipping_method {\n carrier_code\n method_code\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_shipping_method_on_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="644143859">{"data":{"setShippingMethodsOnCart":{"cart":{"shipping_addresses":[{"selected_shipping_method":{"carrier_code":"flatrate","method_code":"flatrate"}}]}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Configurable Product From Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> From 288dec36c94dc7372ccb540095434cab815607f1 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Tue, 9 Apr 2019 10:11:43 -0500 Subject: [PATCH 440/603] 229: [GraphQL caching] Add support for queries via HTTP GET --- .../CatalogInventory/AddProductToCartTest.php | 3 +++ .../Customer/ChangeCustomerPasswordTest.php | 3 +++ .../Customer/CreateCustomerAddressTest.php | 2 +- .../Customer/DeleteCustomerAddressTest.php | 3 +++ .../Customer/SubscriptionStatusTest.php | 3 +++ .../Customer/UpdateCustomerAddressTest.php | 3 +++ .../GraphQl/Customer/UpdateCustomerTest.php | 3 +++ .../AddConfigurableProductToCartTest.php | 3 +++ .../Quote/AddSimpleProductToCartTest.php | 3 +++ .../Quote/Customer/ApplyCouponToCartTest.php | 22 +++++++++---------- .../GraphQl/Quote/Customer/PlaceOrderTest.php | 18 +++++++-------- .../Customer/RemoveCouponFromCartTest.php | 12 +++++----- .../Customer/SetBillingAddressOnCartTest.php | 2 +- .../Customer/SetShippingAddressOnCartTest.php | 2 +- .../Quote/Guest/ApplyCouponToCartTest.php | 20 ++++++++--------- .../Quote/Guest/RemoveCouponFromCartTest.php | 10 ++++----- .../Guest/SetBillingAddressOnCartTest.php | 2 +- .../Guest/SetShippingAddressOnCartTest.php | 2 +- .../GraphQl/SendFriend/SendFriendTest.php | 6 ++++- .../Vault/CustomerPaymentTokensTest.php | 3 +++ 20 files changed, 78 insertions(+), 47 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 0e7ada49dfd38..6616b40257f7d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -13,6 +13,9 @@ use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +/** + * Test for adding products to cart + */ class AddProductToCartTest extends GraphQlAbstract { /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ChangeCustomerPasswordTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ChangeCustomerPasswordTest.php index d147229f55a2d..ab6a1d4b464dd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ChangeCustomerPasswordTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ChangeCustomerPasswordTest.php @@ -14,6 +14,9 @@ use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; +/** + * Test change customer password + */ class ChangeCustomerPasswordTest extends GraphQlAbstract { /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php index eb5dc9e371dcf..891c74ca3c1e2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerAddressTest.php @@ -264,7 +264,7 @@ public function testCreateCustomerAddressWithRedundantStreetLine() $password = 'password'; self::expectExceptionMessage('"Street Address" cannot contain more than 2 lines.'); - $this->graphQlQuery($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); + $this->graphQlMutation($mutation, [], '', $this->getCustomerAuthHeaders($userName, $password)); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/DeleteCustomerAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/DeleteCustomerAddressTest.php index c25d8a7183514..bdfd428a78c20 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/DeleteCustomerAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/DeleteCustomerAddressTest.php @@ -13,6 +13,9 @@ use Magento\TestFramework\TestCase\GraphQlAbstract; use Magento\Integration\Api\CustomerTokenServiceInterface; +/** + * Delete customer address tests + */ class DeleteCustomerAddressTest extends GraphQlAbstract { /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/SubscriptionStatusTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/SubscriptionStatusTest.php index 6d9782dae87d4..2b54c97cd1e97 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/SubscriptionStatusTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/SubscriptionStatusTest.php @@ -12,6 +12,9 @@ use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; +/** + * Tests for subscription status + */ class SubscriptionStatusTest extends GraphQlAbstract { /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerAddressTest.php index bfb07ccf4149c..e7a7eda2897b2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerAddressTest.php @@ -14,6 +14,9 @@ use Magento\TestFramework\TestCase\GraphQlAbstract; use Magento\Integration\Api\CustomerTokenServiceInterface; +/** + * Update customer address tests + */ class UpdateCustomerAddressTest extends GraphQlAbstract { /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php index d4f8053826bcf..08933f47191b9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/UpdateCustomerTest.php @@ -13,6 +13,9 @@ use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; +/** + * Tests for update customer + */ class UpdateCustomerTest extends GraphQlAbstract { /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddConfigurableProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddConfigurableProductToCartTest.php index d8df8db800d8c..f585469177bcd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddConfigurableProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddConfigurableProductToCartTest.php @@ -13,6 +13,9 @@ use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +/** + * Add configurable product to cart tests + */ class AddConfigurableProductToCartTest extends GraphQlAbstract { /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php index 4334a3d6785d6..65ed38ae90f5b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php @@ -13,6 +13,9 @@ use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +/** + * Add simple product to cart tests + */ class AddSimpleProductToCartTest extends GraphQlAbstract { /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php index f0d9400b1866b..5a2221a184294 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/ApplyCouponToCartTest.php @@ -47,7 +47,7 @@ public function testApplyCouponToCart() $couponCode = '2?ds5!2d'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $couponCode); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('applyCouponToCart', $response); self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); @@ -67,12 +67,12 @@ public function testApplyCouponTwice() $couponCode = '2?ds5!2d'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $couponCode); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey("applyCouponToCart", $response); self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -89,7 +89,7 @@ public function testApplyCouponToCartWithoutItems() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -106,7 +106,7 @@ public function testApplyCouponToGuestCart() $query = $this->getQuery($maskedQuoteId, $couponCode); self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -125,7 +125,7 @@ public function testApplyCouponToAnotherCustomerCart() $query = $this->getQuery($maskedQuoteId, $couponCode); self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer_two@example.com')); + $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer_two@example.com')); } /** @@ -142,7 +142,7 @@ public function testApplyNonExistentCouponToCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -159,7 +159,7 @@ public function testApplyCouponToNonExistentCart() $query = $this->getQuery($maskedQuoteId, $couponCode); self::expectExceptionMessage('Could not find a cart with ID "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -179,7 +179,7 @@ public function testApplyExpiredCoupon() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -200,7 +200,7 @@ public function testApplyCouponWhichIsNotApplicable() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -226,7 +226,7 @@ public function testApplyCouponWithMissedRequiredParameters(string $input, strin QUERY; $this->expectExceptionMessage($message); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php index 4220f8932caa1..b7d3b546ba194 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php @@ -77,7 +77,7 @@ public function testPlaceOrder() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); $query = $this->getQuery($maskedQuoteId); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('placeOrder', $response); self::assertArrayHasKey('order_id', $response['placeOrder']['order']); @@ -98,7 +98,7 @@ public function testPlaceOrderWithNoItemsInCart() 'Unable to place order: A server error stopped your order from being placed. ' . 'Please try to place your order again' ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -116,7 +116,7 @@ public function testPlaceOrderWithNoShippingAddress() self::expectExceptionMessage( 'Unable to place order: Some addresses can\'t be used due to the configurations for specific countries' ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -135,7 +135,7 @@ public function testPlaceOrderWithNoShippingMethod() self::expectExceptionMessage( 'Unable to place order: The shipping method is missing. Select the shipping method and try again' ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -156,7 +156,7 @@ public function testPlaceOrderWithNoBillingAddress() self::expectExceptionMessageRegExp( '/Unable to place order: Please check the billing address information*/' ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -176,7 +176,7 @@ public function testPlaceOrderWithNoPaymentMethod() $query = $this->getQuery($maskedQuoteId); self::expectExceptionMessage('Unable to place order: Enter a valid payment method and try again'); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -197,7 +197,7 @@ public function testPlaceOrderWithOutOfStockProduct() $query = $this->getQuery($maskedQuoteId); self::expectExceptionMessage('Unable to place order: Some of the products are out of stock'); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -220,7 +220,7 @@ public function testPlaceOrderOfGuestCart() $query = $this->getQuery($maskedQuoteId); self::expectExceptionMessageRegExp('/The current user cannot perform operations on cart*/'); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -243,7 +243,7 @@ public function testPlaceOrderOfAnotherCustomerCart() $query = $this->getQuery($maskedQuoteId); self::expectExceptionMessageRegExp('/The current user cannot perform operations on cart*/'); - $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer3@search.example.com')); + $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer3@search.example.com')); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveCouponFromCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveCouponFromCartTest.php index feba8c5c64259..ce1c85417b165 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveCouponFromCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveCouponFromCartTest.php @@ -50,7 +50,7 @@ public function testRemoveCouponFromCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('removeCouponFromCart', $response); self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); @@ -66,7 +66,7 @@ public function testRemoveCouponFromNonExistentCart() $maskedQuoteId = 'non_existent_masked_id'; $query = $this->getQuery($maskedQuoteId); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -80,7 +80,7 @@ public function testRemoveCouponFromEmptyCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -94,7 +94,7 @@ public function testRemoveCouponFromCartIfCouponWasNotSet() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('removeCouponFromCart', $response); self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); @@ -115,7 +115,7 @@ public function testRemoveCouponFromGuestCart() $query = $this->getQuery($maskedQuoteId); self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -132,7 +132,7 @@ public function testRemoveCouponFromAnotherCustomerCart() $query = $this->getQuery($maskedQuoteId); self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer3@search.example.com')); + $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer3@search.example.com')); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php index 6cf2209254af9..553408880baa0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php @@ -533,7 +533,7 @@ public function testSetNewBillingAddressWithRedundantStreetLine() } QUERY; self::expectExceptionMessage('"Street Address" cannot contain more than 2 lines.'); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php index af3ff3aab7499..6b097e028ffe5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php @@ -529,7 +529,7 @@ public function testSetNewShippingAddressOnCartWithRedundantStreetLine() QUERY; self::expectExceptionMessage('"Street Address" cannot contain more than 2 lines.'); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php index 045a28834e0dd..affe36ea8617d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php @@ -38,7 +38,7 @@ public function testApplyCouponToCart() $couponCode = '2?ds5!2d'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $couponCode); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('applyCouponToCart', $response); self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); @@ -57,12 +57,12 @@ public function testApplyCouponTwice() $couponCode = '2?ds5!2d'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $couponCode); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey("applyCouponToCart", $response); self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -78,7 +78,7 @@ public function testApplyCouponToCartWithoutItems() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -95,7 +95,7 @@ public function testApplyCouponToCustomerCart() $query = $this->getQuery($maskedQuoteId, $couponCode); self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -111,7 +111,7 @@ public function testApplyNonExistentCouponToCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -125,7 +125,7 @@ public function testApplyCouponToNonExistentCart() $query = $this->getQuery($maskedQuoteId, $couponCode); self::expectExceptionMessage('Could not find a cart with ID "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -144,7 +144,7 @@ public function testApplyExpiredCoupon() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -164,7 +164,7 @@ public function testApplyCouponWhichIsNotApplicable() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -190,7 +190,7 @@ public function testApplyCouponWithMissedRequiredParameters(string $input, strin QUERY; $this->expectExceptionMessage($message); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveCouponFromCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveCouponFromCartTest.php index edb5f9cbf267c..5adb6ce65db6f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveCouponFromCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveCouponFromCartTest.php @@ -42,7 +42,7 @@ public function testRemoveCouponFromCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('removeCouponFromCart', $response); self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); @@ -57,7 +57,7 @@ public function testRemoveCouponFromNonExistentCart() $maskedQuoteId = 'non_existent_masked_id'; $query = $this->getQuery($maskedQuoteId); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -70,7 +70,7 @@ public function testRemoveCouponFromEmptyCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -83,7 +83,7 @@ public function testRemoveCouponFromCartIfCouponWasNotSet() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('removeCouponFromCart', $response); self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); @@ -104,7 +104,7 @@ public function testRemoveCouponFromCustomerCart() $query = $this->getQuery($maskedQuoteId); self::expectExceptionMessage('The current user cannot perform operations on cart "' . $maskedQuoteId . '"'); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php index 96a0fab9348de..5b0e4cfdb6c52 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php @@ -353,7 +353,7 @@ public function testSetNewBillingAddressRedundantStreetLine() QUERY; self::expectExceptionMessage('"Street Address" cannot contain more than 2 lines.'); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php index 009d2cfbb1e55..888b0e87734b6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php @@ -287,7 +287,7 @@ public function testSetNewShippingAddressOnCartWithRedundantStreetLine() } QUERY; self::expectExceptionMessage('"Street Address" cannot contain more than 2 lines.'); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/SendFriend/SendFriendTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/SendFriend/SendFriendTest.php index b40a2b787fe81..ae6faae7650b9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/SendFriend/SendFriendTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/SendFriend/SendFriendTest.php @@ -12,6 +12,9 @@ use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; +/** + * Tests for send email to friend + */ class SendFriendTest extends GraphQlAbstract { @@ -269,7 +272,8 @@ public function testLimitMessagesPerHour() "You can't send messages more than {$sendFriend->getMaxSendsToFriend()} times an hour." ); - for ($i = 0; $i <= $sendFriend->getMaxSendsToFriend() + 1; $i++) { + $maxSendToFriends = $sendFriend->getMaxSendsToFriend(); + for ($i = 0; $i <= $maxSendToFriends + 1; $i++) { $this->graphQlMutation($query); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Vault/CustomerPaymentTokensTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Vault/CustomerPaymentTokensTest.php index b2d89828f211f..45c82906d255d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Vault/CustomerPaymentTokensTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Vault/CustomerPaymentTokensTest.php @@ -14,6 +14,9 @@ use Magento\Vault\Model\ResourceModel\PaymentToken as TokenResource; use Magento\Vault\Model\ResourceModel\PaymentToken\CollectionFactory; +/** + * Tests for customer payment tokens + */ class CustomerPaymentTokensTest extends GraphQlAbstract { /** From 75684cadfe6231e352c959cbd0648612489b533a Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta <riccardo.tempesta@gmail.com> Date: Tue, 9 Apr 2019 18:38:04 +0200 Subject: [PATCH 441/603] Added test coverage for virtual types code generation --- .../Code/Test/Unit/GeneratorTest.php | 169 +++++++++++++++--- 1 file changed, 140 insertions(+), 29 deletions(-) diff --git a/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php b/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php index 9cc93f7620b1f..98700ae8917f1 100644 --- a/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php +++ b/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php @@ -3,11 +3,15 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Framework\Code\Test\Unit; use Magento\Framework\Code\Generator; use Magento\Framework\Code\Generator\DefinedClasses; use Magento\Framework\Code\Generator\Io; +use Magento\Framework\ObjectManager\ConfigInterface; +use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; use Magento\Framework\ObjectManager\Code\Generator\Factory; use Magento\Framework\ObjectManager\Code\Generator\Proxy; @@ -17,13 +21,14 @@ use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Code\Generator\EntityAbstract; use Magento\GeneratedClass\Factory as GeneratedClassFactory; +use RuntimeException; class GeneratorTest extends TestCase { /** * Class name parameter value */ - const SOURCE_CLASS = 'testClassName'; + private const SOURCE_CLASS = 'testClassName'; /** * Expected generated entities @@ -58,6 +63,19 @@ class GeneratorTest extends TestCase */ private $loggerMock; + /** + * @var ObjectManagerInterface|MockObject + */ + private $objectManagerMock; + + /** + * @var ConfigInterface|MockObject + */ + private $objectManagerConfigMock; + + /** + * @inheritDoc + */ protected function setUp() { $this->definedClassesMock = $this->createMock(DefinedClasses::class); @@ -65,6 +83,12 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); $this->loggerMock = $this->getMockForAbstractClass(LoggerInterface::class); + $this->objectManagerMock = $this->getMockBuilder(ObjectManagerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->objectManagerConfigMock = $this->getMockBuilder(ConfigInterface::class) + ->disableOriginalConstructor() + ->getMock(); $this->model = new Generator( $this->ioObjectMock, @@ -78,7 +102,7 @@ protected function setUp() ); } - public function testGetGeneratedEntities() + public function testGetGeneratedEntities(): void { $this->model = new Generator( $this->ioObjectMock, @@ -91,22 +115,58 @@ public function testGetGeneratedEntities() /** * @param string $className * @param string $entityType - * @expectedException \RuntimeException + * @expectedException RuntimeException * @dataProvider generateValidClassDataProvider */ - public function testGenerateClass($className, $entityType) + public function testGenerateClass($className, $entityType): void { - $objectManagerMock = $this->createMock(ObjectManagerInterface::class); $fullClassName = $className . $entityType; + $entityGeneratorMock = $this->getMockBuilder(EntityAbstract::class) ->disableOriginalConstructor() ->getMock(); - $objectManagerMock->expects($this->once())->method('create')->willReturn($entityGeneratorMock); - $this->model->setObjectManager($objectManagerMock); - $this->model->generateClass($fullClassName); + $this->objectManagerMock + ->expects($this->once()) + ->method('create') + ->willReturn($entityGeneratorMock); + + $this->objectManagerConfigMock + ->expects($this->once()) + ->method('getVirtualTypes') + ->willReturn([]); + $this->objectManagerMock + ->expects($this->once()) + ->method('get') + ->with(ConfigInterface::class) + ->willReturn($this->objectManagerConfigMock); + $this->model->setObjectManager($this->objectManagerMock); + + $this->assertSame( + Generator::GENERATION_SUCCESS, + $this->model->generateClass(GeneratedClassFactory::class) + ); } - public function testGenerateClassWithWrongName() + public function testShouldNotGenerateVirtualType(): void + { + $this->objectManagerConfigMock + ->expects($this->once()) + ->method('getVirtualTypes') + ->willReturn([GeneratedClassFactory::class => GeneratedClassFactory::class]); + $this->objectManagerMock + ->expects($this->once()) + ->method('get') + ->with(ConfigInterface::class) + ->willReturn($this->objectManagerConfigMock); + $this->model->setObjectManager($this->objectManagerMock); + + $this->assertSame( + Generator::GENERATION_SKIP, + $this->model->generateClass(GeneratedClassFactory::class) + ); + } + + public function testGenerateClassWithWrongName(): void { $this->assertEquals( Generator::GENERATION_ERROR, @@ -115,25 +175,42 @@ public function testGenerateClassWithWrongName() } /** - * @expectedException \RuntimeException + * @expectedException RuntimeException */ - public function testGenerateClassWhenClassIsNotGenerationSuccess() + public function testGenerateClassWhenClassIsNotGenerationSuccess(): void { $expectedEntities = array_values($this->expectedEntities); $resultClassName = self::SOURCE_CLASS . ucfirst(array_shift($expectedEntities)); - $objectManagerMock = $this->createMock(ObjectManagerInterface::class); + $entityGeneratorMock = $this->getMockBuilder(EntityAbstract::class) ->disableOriginalConstructor() ->getMock(); - $objectManagerMock->expects($this->once())->method('create')->willReturn($entityGeneratorMock); - $this->model->setObjectManager($objectManagerMock); - $this->model->generateClass($resultClassName); + $this->objectManagerMock + ->expects($this->once()) + ->method('create') + ->willReturn($entityGeneratorMock); + + $this->objectManagerConfigMock + ->expects($this->once()) + ->method('getVirtualTypes') + ->willReturn([]); + $this->objectManagerMock + ->expects($this->once()) + ->method('get') + ->with(ConfigInterface::class) + ->willReturn($this->objectManagerConfigMock); + $this->model->setObjectManager($this->objectManagerMock); + + $this->assertSame( + Generator::GENERATION_SUCCESS, + $this->model->generateClass($resultClassName) + ); } /** * @inheritdoc */ - public function testGenerateClassWithErrors() + public function testGenerateClassWithErrors(): void { $expectedEntities = array_values($this->expectedEntities); $resultClassName = self::SOURCE_CLASS . ucfirst(array_shift($expectedEntities)); @@ -148,17 +225,15 @@ public function testGenerateClassWithErrors() . 'directory permission is set to write --- the requested class did not generate properly, then ' . 'you must add the generated class object to the signature of the related construct method, only.'; $FinalErrorMessage = implode(PHP_EOL, $errorMessages) . "\n" . $mainErrorMessage; - $this->expectException(\RuntimeException::class); + $this->expectException(RuntimeException::class); $this->expectExceptionMessage($FinalErrorMessage); - /** @var ObjectManagerInterface|Mock $objectManagerMock */ - $objectManagerMock = $this->createMock(ObjectManagerInterface::class); /** @var EntityAbstract|Mock $entityGeneratorMock */ $entityGeneratorMock = $this->getMockBuilder(EntityAbstract::class) ->disableOriginalConstructor() ->getMock(); - $objectManagerMock->expects($this->once()) + $this->objectManagerMock->expects($this->once()) ->method('create') ->willReturn($entityGeneratorMock); $entityGeneratorMock->expects($this->once()) @@ -177,26 +252,62 @@ public function testGenerateClassWithErrors() $this->loggerMock->expects($this->once()) ->method('critical') ->with($FinalErrorMessage); - $this->model->setObjectManager($objectManagerMock); - $this->model->generateClass($resultClassName); + + $this->objectManagerConfigMock + ->expects($this->once()) + ->method('getVirtualTypes') + ->willReturn([]); + $this->objectManagerMock + ->expects($this->once()) + ->method('get') + ->with(ConfigInterface::class) + ->willReturn($this->objectManagerConfigMock); + $this->model->setObjectManager($this->objectManagerMock); + + $this->assertSame( + Generator::GENERATION_SUCCESS, + $this->model->generateClass($resultClassName) + ); } /** * @dataProvider trueFalseDataProvider + * @param $fileExists */ - public function testGenerateClassWithExistName($fileExists) + public function testGenerateClassWithExistName($fileExists): void { $this->definedClassesMock->expects($this->any()) ->method('isClassLoadableFromDisk') ->willReturn(true); $resultClassFileName = '/Magento/Path/To/Class.php'; - $this->ioObjectMock->expects($this->once())->method('generateResultFileName')->willReturn($resultClassFileName); - $this->ioObjectMock->expects($this->once())->method('fileExists')->willReturn($fileExists); + + $this->objectManagerConfigMock + ->expects($this->once()) + ->method('getVirtualTypes') + ->willReturn([]); + $this->objectManagerMock + ->expects($this->once()) + ->method('get') + ->with(ConfigInterface::class) + ->willReturn($this->objectManagerConfigMock); + $this->model->setObjectManager($this->objectManagerMock); + + $this->ioObjectMock + ->expects($this->once()) + ->method('generateResultFileName') + ->willReturn($resultClassFileName); + $this->ioObjectMock + ->expects($this->once()) + ->method('fileExists') + ->willReturn($fileExists); + $includeFileInvokeCount = $fileExists ? 1 : 0; - $this->ioObjectMock->expects($this->exactly($includeFileInvokeCount))->method('includeFile'); + $this->ioObjectMock + ->expects($this->exactly($includeFileInvokeCount)) + ->method('includeFile'); - $this->assertEquals( + $this->assertSame( Generator::GENERATION_SKIP, $this->model->generateClass(GeneratedClassFactory::class) ); @@ -205,7 +316,7 @@ public function testGenerateClassWithExistName($fileExists) /** * @return array */ - public function trueFalseDataProvider() + public function trueFalseDataProvider(): array { return [[true], [false]]; } @@ -215,7 +326,7 @@ public function trueFalseDataProvider() * * @return array */ - public function generateValidClassDataProvider() + public function generateValidClassDataProvider(): array { $data = []; foreach ($this->expectedEntities as $generatedEntity) { From 0135d54081229cacbf68699a12f675653c7325ad Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Tue, 9 Apr 2019 13:12:02 -0500 Subject: [PATCH 442/603] MC-15734: Create new GraphQL script for our benchmark - part 2 --- setup/performance-toolkit/benchmark.jmx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 31ccf845a625d..cfabe613a0ea1 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -409,9 +409,9 @@ <stringProp name="Argument.value">${__P(graphqlGetNavigationMenuByCategoryIdPercentage,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="graphqlGetProductSearchByProductNamePercentage" elementType="Argument"> - <stringProp name="Argument.name">graphqlGetProductSearchByProductNamePercentage</stringProp> - <stringProp name="Argument.value">${__P(graphqlGetProductSearchByProductNamePercentage,0)}</stringProp> + <elementProp name="graphqlGetProductDetailByProductNamePercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlGetProductDetailByProductNamePercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlGetProductDetailByProductNamePercentage,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="graphqlGetProductSearchByTextAndCategoryIdPercentage" elementType="Argument"> @@ -39803,11 +39803,11 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Product Search by product_name" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Product Detail by product_name" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlGetProductSearchByProductNamePercentage}</stringProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlGetProductDetailByProductNamePercentage}</stringProp> <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> <hashTree> <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> @@ -39828,7 +39828,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Get Product Search by product_name"); + vars.put("testLabel", "Get Product Detail by product_name"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -39886,7 +39886,7 @@ vars.put("product_sku", product.get("sku")); <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Product Search by product_name" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Product Detail by product_name" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> @@ -39911,7 +39911,7 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_product_search_by_product_name.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_product_detail_by_product_name.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> From df413f51a0ec509358173b76322735d620a5c0d0 Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Tue, 9 Apr 2019 14:45:54 -0500 Subject: [PATCH 443/603] MC-15779: Create coupon test functionality for our benchmark --- .../profiles/ce/extra_large.xml | 1 + .../performance-toolkit/profiles/ce/large.xml | 1 + .../profiles/ce/medium.xml | 1 + .../profiles/ce/medium_msite.xml | 1 + .../performance-toolkit/profiles/ce/small.xml | 1 + .../Setup/Fixtures/CouponCodesFixture.php | 164 +++++++++++++++ .../Unit/Fixtures/CouponCodesFixtureTest.php | 198 ++++++++++++++++++ 7 files changed, 367 insertions(+) create mode 100644 setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php create mode 100644 setup/src/Magento/Setup/Test/Unit/Fixtures/CouponCodesFixtureTest.php diff --git a/setup/performance-toolkit/profiles/ce/extra_large.xml b/setup/performance-toolkit/profiles/ce/extra_large.xml index 390bf7fb12003..911ac7fe06d3b 100644 --- a/setup/performance-toolkit/profiles/ce/extra_large.xml +++ b/setup/performance-toolkit/profiles/ce/extra_large.xml @@ -39,6 +39,7 @@ <catalog_price_rules>20</catalog_price_rules> <!-- Number of catalog price rules --> <cart_price_rules>20</cart_price_rules> <!-- Number of cart price rules --> <cart_price_rules_floor>2</cart_price_rules_floor> + <coupon_codes>20</coupon_codes> <!-- Number of coupon codes --> <product_attribute_sets>100</product_attribute_sets> <!-- Number of product attribute sets --> <product_attribute_sets_attributes>30</product_attribute_sets_attributes> <!-- Number of attributes per set --> diff --git a/setup/performance-toolkit/profiles/ce/large.xml b/setup/performance-toolkit/profiles/ce/large.xml index ed91b22930af5..79abab0ba4b95 100644 --- a/setup/performance-toolkit/profiles/ce/large.xml +++ b/setup/performance-toolkit/profiles/ce/large.xml @@ -39,6 +39,7 @@ <catalog_price_rules>20</catalog_price_rules> <!-- Number of catalog price rules --> <cart_price_rules>20</cart_price_rules> <!-- Number of cart price rules --> <cart_price_rules_floor>2</cart_price_rules_floor> + <coupon_codes>20</coupon_codes> <!-- Number of coupon codes --> <product_attribute_sets>50</product_attribute_sets> <!-- Number of product attribute sets --> <product_attribute_sets_attributes>20</product_attribute_sets_attributes> <!-- Number of attributes per set --> diff --git a/setup/performance-toolkit/profiles/ce/medium.xml b/setup/performance-toolkit/profiles/ce/medium.xml index f01eabb7898f3..d02370a7770b3 100644 --- a/setup/performance-toolkit/profiles/ce/medium.xml +++ b/setup/performance-toolkit/profiles/ce/medium.xml @@ -39,6 +39,7 @@ <catalog_price_rules>20</catalog_price_rules> <!-- Number of catalog price rules --> <cart_price_rules>20</cart_price_rules> <!-- Number of cart price rules --> <cart_price_rules_floor>2</cart_price_rules_floor> + <coupon_codes>20</coupon_codes> <!-- Number of coupon codes --> <product_attribute_sets>30</product_attribute_sets> <!-- Number of product attribute sets --> <product_attribute_sets_attributes>10</product_attribute_sets_attributes> <!-- Number of attributes per set --> diff --git a/setup/performance-toolkit/profiles/ce/medium_msite.xml b/setup/performance-toolkit/profiles/ce/medium_msite.xml index a57fcad0779fe..2f9310c5242cb 100644 --- a/setup/performance-toolkit/profiles/ce/medium_msite.xml +++ b/setup/performance-toolkit/profiles/ce/medium_msite.xml @@ -45,6 +45,7 @@ <catalog_price_rules>20</catalog_price_rules> <!-- Number of catalog price rules --> <cart_price_rules>20</cart_price_rules> <!-- Number of cart price rules --> <cart_price_rules_floor>2</cart_price_rules_floor> + <coupon_codes>20</coupon_codes> <!-- Number of coupon codes --> <product_attribute_sets>30</product_attribute_sets> <!-- Number of product attribute sets --> <product_attribute_sets_attributes>10</product_attribute_sets_attributes> <!-- Number of attributes per set --> diff --git a/setup/performance-toolkit/profiles/ce/small.xml b/setup/performance-toolkit/profiles/ce/small.xml index 60ae901d8f5e0..cf7768328bd69 100644 --- a/setup/performance-toolkit/profiles/ce/small.xml +++ b/setup/performance-toolkit/profiles/ce/small.xml @@ -39,6 +39,7 @@ <catalog_price_rules>20</catalog_price_rules> <!-- Number of catalog price rules --> <cart_price_rules>20</cart_price_rules> <!-- Number of cart price rules --> <cart_price_rules_floor>2</cart_price_rules_floor> + <coupon_codes>20</coupon_codes> <!-- Number of coupon codes --> <product_attribute_sets>10</product_attribute_sets> <!-- Number of product attribute sets --> <product_attribute_sets_attributes>5</product_attribute_sets_attributes> <!-- Number of attributes per set --> diff --git a/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php b/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php new file mode 100644 index 0000000000000..31e5ab9ebd575 --- /dev/null +++ b/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php @@ -0,0 +1,164 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Fixtures; + +/** + * Fixture for generating coupon codes + * + * Support the following format: + * <!-- Number of coupon codes --> + * <coupon_codes>{int}</coupon_codes> + * + * @see setup/performance-toolkit/profiles/ce/small.xml + */ +class CouponCodesFixture extends Fixture +{ + /** + * @var int + */ + protected $priority = 130; + + /** + * @var int + */ + protected $couponCodesCount = 0; + + /** + * @var \Magento\SalesRule\Model\RuleFactory + */ + private $ruleFactory; + + /** + * @var \Magento\SalesRule\Model\CouponFactory + */ + private $couponCodeFactory; + + /** + * Constructor + * + * @param FixtureModel $fixtureModel + * @param \Magento\SalesRule\Model\RuleFactory|null $ruleFactory + * @param \Magento\SalesRule\Model\CouponFactory|null $couponCodeFactory + */ + public function __construct( + FixtureModel $fixtureModel, + \Magento\SalesRule\Model\RuleFactory $ruleFactory = null, + \Magento\SalesRule\Model\CouponFactory $couponCodeFactory = null + ) { + parent::__construct($fixtureModel); + $this->ruleFactory = $ruleFactory ?: $this->fixtureModel->getObjectManager() + ->get(\Magento\SalesRule\Model\RuleFactory::class); + $this->couponCodeFactory = $couponCodeFactory ?: $this->fixtureModel->getObjectManager() + ->get(\Magento\SalesRule\Model\CouponFactory::class); + } + + /** + * {@inheritdoc} + * @SuppressWarnings(PHPMD) + */ + public function execute() + { + $this->fixtureModel->resetObjectManager(); + $this->couponCodesCount = $this->fixtureModel->getValue('coupon_codes', 0); + if (!$this->couponCodesCount) { + return; + } + + /** @var \Magento\Store\Model\StoreManager $storeManager */ + $storeManager = $this->fixtureModel->getObjectManager()->create(\Magento\Store\Model\StoreManager::class); + /** @var $category \Magento\Catalog\Model\Category */ + $category = $this->fixtureModel->getObjectManager()->get(\Magento\Catalog\Model\Category::class); + + //Get all websites + $categoriesArray = []; + $websites = $storeManager->getWebsites(); + foreach ($websites as $website) { + //Get all groups + $websiteGroups = $website->getGroups(); + foreach ($websiteGroups as $websiteGroup) { + $websiteGroupRootCategory = $websiteGroup->getRootCategoryId(); + $category->load($websiteGroupRootCategory); + $categoryResource = $category->getResource(); + //Get all categories + $resultsCategories = $categoryResource->getAllChildren($category); + foreach ($resultsCategories as $resultsCategory) { + $category->load($resultsCategory); + $structure = explode('/', $category->getPath()); + if (count($structure) > 2) { + $categoriesArray[] = [$category->getId(), $website->getId()]; + } + } + } + } + asort($categoriesArray); + $categoriesArray = array_values($categoriesArray); + + $this->generateCouponCodes($this->ruleFactory, $this->couponCodeFactory, $categoriesArray); + } + + /** + * @param \Magento\SalesRule\Model\RuleFactory $ruleFactory + * @param \Magento\SalesRule\Model\CouponFactory $couponCodeFactory + * @param array $categoriesArray + * @return void + */ + public function generateCouponCodes($ruleFactory, $couponCodeFactory, $categoriesArray) + { + for ($i = 0; $i < $this->couponCodesCount; $i++) { + $ruleName = sprintf('Coupon Code %1$d', $i); + $data = [ + 'rule_id' => null, + 'name' => $ruleName, + 'is_active' => '1', + 'website_ids' => $categoriesArray[$i % count($categoriesArray)][1], + 'customer_group_ids' => [ + 0 => '0', + 1 => '1', + 2 => '2', + 3 => '3', + ], + 'coupon_type' => \Magento\SalesRule\Model\Rule::COUPON_TYPE_SPECIFIC, + 'conditions' => [], + 'simple_action' => \Magento\SalesRule\Model\Rule::BY_PERCENT_ACTION, + 'discount_amount' => 5, + 'discount_step' => 0, + 'stop_rules_processing' => 1, + ]; + + $model = $ruleFactory->create(); + $model->loadPost($data); + $useAutoGeneration = (int)!empty($data['use_auto_generation']); + $model->setUseAutoGeneration($useAutoGeneration); + $model->save(); + + $coupon = $couponCodeFactory->create(); + $coupon->setRuleId($model->getId()) + ->setCode('CouponCode' . $i) + ->setIsPrimary(true) + ->setType(0); + $coupon->save(); + } + } + + /** + * {@inheritdoc} + */ + public function getActionTitle() + { + return 'Generating coupon codes'; + } + + /** + * {@inheritdoc} + */ + public function introduceParamLabels() + { + return [ + 'coupon_codes' => 'Coupon Codes' + ]; + } +} diff --git a/setup/src/Magento/Setup/Test/Unit/Fixtures/CouponCodesFixtureTest.php b/setup/src/Magento/Setup/Test/Unit/Fixtures/CouponCodesFixtureTest.php new file mode 100644 index 0000000000000..e28415961f26a --- /dev/null +++ b/setup/src/Magento/Setup/Test/Unit/Fixtures/CouponCodesFixtureTest.php @@ -0,0 +1,198 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Test\Unit\Fixtures; + +use \Magento\Setup\Fixtures\CouponCodesFixture; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class CouponCodesFixtureTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var \Magento\Setup\Fixtures\CartPriceRulesFixture + */ + private $model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Setup\Fixtures\FixtureModel + */ + private $fixtureModelMock; + + /** + * @var \Magento\SalesRule\Model\RuleFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $ruleFactoryMock; + + /** + * @var \Magento\SalesRule\Model\CouponFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $couponCodeFactoryMock; + + /** + * setUp + */ + public function setUp() + { + $this->fixtureModelMock = $this->createMock(\Magento\Setup\Fixtures\FixtureModel::class); + $this->ruleFactoryMock = $this->createPartialMock(\Magento\SalesRule\Model\RuleFactory::class, ['create']); + $this->couponCodeFactoryMock = $this->createPartialMock( + \Magento\SalesRule\Model\CouponFactory::class, + ['create'] + ); + $this->model = new CouponCodesFixture( + $this->fixtureModelMock, + $this->ruleFactoryMock, + $this->couponCodeFactoryMock + ); + } + + /** + * testExecute + */ + public function testExecute() + { + $storeMock = $this->createMock(\Magento\Store\Model\Store::class); + $storeMock->expects($this->once()) + ->method('getRootCategoryId') + ->will($this->returnValue(2)); + + $websiteMock = $this->createMock(\Magento\Store\Model\Website::class); + $websiteMock->expects($this->once()) + ->method('getGroups') + ->will($this->returnValue([$storeMock])); + $websiteMock->expects($this->once()) + ->method('getId') + ->will($this->returnValue('website_id')); + + $contextMock = $this->createMock(\Magento\Framework\Model\ResourceModel\Db\Context::class); + $abstractDbMock = $this->getMockForAbstractClass( + \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + [$contextMock], + '', + true, + true, + true, + ['getAllChildren'] + ); + $abstractDbMock->expects($this->once()) + ->method('getAllChildren') + ->will($this->returnValue([1])); + + $storeManagerMock = $this->createMock(\Magento\Store\Model\StoreManager::class); + $storeManagerMock->expects($this->once()) + ->method('getWebsites') + ->will($this->returnValue([$websiteMock])); + + $categoryMock = $this->createMock(\Magento\Catalog\Model\Category::class); + $categoryMock->expects($this->once()) + ->method('getResource') + ->will($this->returnValue($abstractDbMock)); + $categoryMock->expects($this->once()) + ->method('getPath') + ->will($this->returnValue('path/to/file')); + $categoryMock->expects($this->once()) + ->method('getId') + ->will($this->returnValue('category_id')); + + $objectValueMap = [ + [\Magento\Catalog\Model\Category::class, $categoryMock] + ]; + + $objectManagerMock = $this->createMock(\Magento\Framework\ObjectManager\ObjectManager::class); + $objectManagerMock->expects($this->once()) + ->method('create') + ->will($this->returnValue($storeManagerMock)); + $objectManagerMock->expects($this->once()) + ->method('get') + ->will($this->returnValueMap($objectValueMap)); + + $valueMap = [ + ['coupon_codes', 0, 1] + ]; + + $this->fixtureModelMock + ->expects($this->exactly(1)) + ->method('getValue') + ->will($this->returnValueMap($valueMap)); + $this->fixtureModelMock + ->expects($this->exactly(2)) + ->method('getObjectManager') + ->will($this->returnValue($objectManagerMock)); + + $ruleMock = $this->createMock(\Magento\SalesRule\Model\Rule::class); + $this->ruleFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($ruleMock); + + $couponMock = $this->createMock(\Magento\SalesRule\Model\Coupon::class); + $couponMock->expects($this->once()) + ->method('setRuleId') + ->willReturnSelf(); + $couponMock->expects($this->once()) + ->method('setCode') + ->willReturnSelf(); + $couponMock->expects($this->once()) + ->method('setIsPrimary') + ->willReturnSelf(); + $couponMock->expects($this->once()) + ->method('setType') + ->willReturnSelf(); + $couponMock->expects($this->once()) + ->method('save') + ->willReturnSelf(); + $this->couponCodeFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($couponMock); + + $this->model->execute(); + } + + /** + * testNoFixtureConfigValue + */ + public function testNoFixtureConfigValue() + { + $ruleMock = $this->createMock(\Magento\SalesRule\Model\Rule::class); + $ruleMock->expects($this->never())->method('save'); + + $objectManagerMock = $this->createMock(\Magento\Framework\ObjectManager\ObjectManager::class); + $objectManagerMock->expects($this->never()) + ->method('get') + ->with($this->equalTo(\Magento\SalesRule\Model\Rule::class)) + ->willReturn($ruleMock); + + $this->fixtureModelMock + ->expects($this->never()) + ->method('getObjectManager') + ->willReturn($objectManagerMock); + $this->fixtureModelMock + ->expects($this->once()) + ->method('getValue') + ->willReturn(false); + + $this->model->execute(); + } + + /** + * testGetActionTitle + */ + public function testGetActionTitle() + { + $this->assertSame('Generating coupon codes', $this->model->getActionTitle()); + } + + /** + * testIntroduceParamLabels + */ + public function testIntroduceParamLabels() + { + $this->assertSame([ + 'coupon_codes' => 'Coupon Codes' + ], $this->model->introduceParamLabels()); + } +} From 361f5485ed0081c5ecb25db4a5fa5e282b143b04 Mon Sep 17 00:00:00 2001 From: Viktor Tymchynskyi <vtymchynskyi@magento.com> Date: Tue, 9 Apr 2019 13:22:31 -0500 Subject: [PATCH 444/603] MAGETWO-99094: Orders in PayPal, but not created in Magento due to missing credit card exp_month - Expiration month and year read from PayPal response --- .../Payflow/Service/Response/Transaction.php | 51 ++++++- .../Controller/Transparent/ResponseTest.php | 134 ++++++++++++++++++ 2 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/Controller/Transparent/ResponseTest.php diff --git a/app/code/Magento/Paypal/Model/Payflow/Service/Response/Transaction.php b/app/code/Magento/Paypal/Model/Payflow/Service/Response/Transaction.php index 06a8a5b680bf4..7143576b71a07 100644 --- a/app/code/Magento/Paypal/Model/Payflow/Service/Response/Transaction.php +++ b/app/code/Magento/Paypal/Model/Payflow/Service/Response/Transaction.php @@ -3,9 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Paypal\Model\Payflow\Service\Response; use Magento\Framework\DataObject; +use Magento\Framework\Intl\DateTimeFactory; use Magento\Payment\Model\Method\Logger; use Magento\Paypal\Model\Payflow\Service\Response\Handler\HandlerInterface; use Magento\Framework\Session\Generic; @@ -18,6 +21,7 @@ /** * Class Transaction + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Transaction { @@ -51,6 +55,11 @@ class Transaction */ private $logger; + /** + * @var DateTimeFactory + */ + private $dateTimeFactory; + /** * @param Generic $sessionTransparent * @param CartRepositoryInterface $quoteRepository @@ -58,6 +67,7 @@ class Transaction * @param PaymentMethodManagementInterface $paymentManagement * @param HandlerInterface $errorHandler * @param Logger $logger + * @param DateTimeFactory $dateTimeFactory */ public function __construct( Generic $sessionTransparent, @@ -65,7 +75,8 @@ public function __construct( Transparent $transparent, PaymentMethodManagementInterface $paymentManagement, HandlerInterface $errorHandler, - Logger $logger + Logger $logger, + DateTimeFactory $dateTimeFactory ) { $this->sessionTransparent = $sessionTransparent; $this->quoteRepository = $quoteRepository; @@ -73,6 +84,7 @@ public function __construct( $this->paymentManagement = $paymentManagement; $this->errorHandler = $errorHandler; $this->logger = $logger; + $this->dateTimeFactory = $dateTimeFactory; } /** @@ -114,8 +126,45 @@ public function savePaymentInQuote($response) $payment->setData(OrderPaymentInterface::CC_TYPE, $response->getData(OrderPaymentInterface::CC_TYPE)); $payment->setAdditionalInformation(Payflowpro::PNREF, $response->getData(Payflowpro::PNREF)); + $expDate = $response->getData('expdate'); + $expMonth = $this->getCcExpMonth($expDate); + $payment->setCcExpMonth($expMonth); + $expYear = $this->getCcExpYear($expDate); + $payment->setCcExpYear($expYear); + $this->errorHandler->handle($payment, $response); $this->paymentManagement->set($quote->getId(), $payment); } + + /** + * Extracts expiration month from PayPal response expiration date. + * + * @param string $expDate format {MMYY} + * @return int + */ + private function getCcExpMonth(string $expDate): int + { + return (int)substr($expDate, 0, 2); + } + + /** + * Extracts expiration year from PayPal response expiration date. + * + * @param string $expDate format {MMYY} + * @return int + */ + private function getCcExpYear(string $expDate): int + { + $last2YearDigits = (int)substr($expDate, 2, 2); + $currentDate = $this->dateTimeFactory->create('now', new \DateTimeZone('UTC')); + $first2YearDigits = (int)substr($currentDate->format('Y'), 0, 2); + + // case when credit card expires at next century + if ((int)$currentDate->format('y') > $last2YearDigits) { + $first2YearDigits++; + } + + return 100 * $first2YearDigits + $last2YearDigits; + } } diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Controller/Transparent/ResponseTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Controller/Transparent/ResponseTest.php new file mode 100644 index 0000000000000..17464b6d65861 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/Controller/Transparent/ResponseTest.php @@ -0,0 +1,134 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Paypal\Controller\Transparent; + +use Magento\Checkout\Model\Session; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Intl\DateTimeFactory; +use Magento\Framework\Session\Generic as GenericSession; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Api\Data\CartInterface; +use Magento\Quote\Api\PaymentMethodManagementInterface; + +/** + * Tests PayPal transparent response controller. + */ +class ResponseTest extends \Magento\TestFramework\TestCase\AbstractController +{ + /** + * Tests setting credit card expiration month and year to payment from PayPal response. + * + * @param string $currentDateTime + * @param string $paypalExpDate + * @param string $expectedCcMonth + * @param string $expectedCcYear + * @throws NoSuchEntityException + * + * @magentoConfigFixture current_store payment/payflowpro/active 1 + * @magentoDataFixture Magento/Sales/_files/quote.php + * @dataProvider paymentCcExpirationDateDataProvider + */ + public function testPaymentCcExpirationDate( + string $currentDateTime, + string $paypalExpDate, + string $expectedCcMonth, + string $expectedCcYear + ) { + $reservedOrderId = 'test01'; + $postData = [ + 'EXPDATE' => $paypalExpDate, + 'AMT' => '0.00', + 'RESPMSG' => 'Verified', + 'CVV2MATCH' => 'Y', + 'PNREF' => 'A10AAD866C87', + 'SECURETOKEN' => '3HYEHfG06skydAdBXbpIl8QJZ', + 'AVSDATA' => 'YNY', + 'RESULT' => '0', + 'IAVS' => 'N', + 'AVSADDR' => 'Y', + 'SECURETOKENID' => 'yqanLisRZbI0HAG8q3SbbKbhiwjNZAGf', + ]; + + $quote = $this->getQuote($reservedOrderId); + $this->getRequest()->setPostValue($postData); + + /** @var Session $checkoutSession */ + $checkoutSession = $this->_objectManager->get(GenericSession::class); + $checkoutSession->setQuoteId($quote->getId()); + $this->setCurrentDateTime($currentDateTime); + + $this->dispatch('paypal/transparent/response'); + + /** @var PaymentMethodManagementInterface $paymentManagment */ + $paymentManagment = $this->_objectManager->get(PaymentMethodManagementInterface::class); + $payment = $paymentManagment->get($quote->getId()); + + $this->assertEquals($expectedCcMonth, $payment->getCcExpMonth()); + $this->assertEquals($expectedCcYear, $payment->getCcExpYear()); + } + + /** + * @return array + */ + public function paymentCcExpirationDateDataProvider(): array + { + return [ + 'Expiration year in current century' => [ + 'currentDateTime' => '2019-07-05 00:00:00', + 'paypalExpDate' => '0321', + 'expectedCcMonth' => 3, + 'expectedCcYear' => 2021 + ], + 'Expiration year in next century' => [ + 'currentDateTime' => '2099-01-01 00:00:00', + 'paypalExpDate' => '1002', + 'expectedCcMonth' => 10, + 'expectedCcYear' => 2102 + ] + ]; + } + + /** + * Sets current date and time. + * + * @param string $date + */ + private function setCurrentDateTime(string $dateTime): void + { + $dateTime = new \DateTime($dateTime, new \DateTimeZone('UTC')); + $dateTimeFactory = $this->getMockBuilder(DateTimeFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $dateTimeFactory->method('create') + ->willReturn($dateTime); + + $this->_objectManager->addSharedInstance($dateTimeFactory, DateTimeFactory::class); + } + + /** + * Gets quote by reserved order ID. + * + * @param string $reservedOrderId + * @return CartInterface + */ + private function getQuote(string $reservedOrderId): CartInterface + { + $searchCriteria = $this->_objectManager->get(SearchCriteriaBuilder::class) + ->addFilter('reserved_order_id', $reservedOrderId) + ->create(); + + /** @var CartRepositoryInterface $quoteRepository */ + $quoteRepository = $this->_objectManager->get(CartRepositoryInterface::class); + $items = $quoteRepository->getList($searchCriteria) + ->getItems(); + + return array_pop($items); + } +} From 2e01743926de7410d160aebdedd4f2ccbfdaddcf Mon Sep 17 00:00:00 2001 From: Vova Yatsyuk <vova.yatsyuk@gmail.com> Date: Wed, 10 Apr 2019 10:40:20 +0300 Subject: [PATCH 445/603] Use proper variables for tooltip styles on tablet devices --- .../web/css/source/module/checkout/_tooltip.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less index 664726ddfd798..abc990c56f651 100644 --- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less @@ -173,10 +173,10 @@ width: 0; } .field-tooltip .field-tooltip-content::before { - border-bottom-color: @color-gray40; + border-bottom-color: @checkout-tooltip-content__border-color; } .field-tooltip .field-tooltip-content::after { - border-bottom-color: @color-gray-light01; + border-bottom-color: @checkout-tooltip-content__background-color; top: 1px; } } From 62fed32a567bbdf018b0b0c8e9631d44cc48194d Mon Sep 17 00:00:00 2001 From: Rafael Kassner <kassner@gmail.com> Date: Wed, 10 Apr 2019 12:20:12 +0200 Subject: [PATCH 446/603] Show the correct subtotal amount for partial creditmemos --- .../frontend/templates/email/items/creditmemo/default.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/view/frontend/templates/email/items/creditmemo/default.phtml b/app/code/Magento/Sales/view/frontend/templates/email/items/creditmemo/default.phtml index 1fca65932b0b0..20c2c1869fedb 100644 --- a/app/code/Magento/Sales/view/frontend/templates/email/items/creditmemo/default.phtml +++ b/app/code/Magento/Sales/view/frontend/templates/email/items/creditmemo/default.phtml @@ -31,6 +31,6 @@ </td> <td class="item-qty"><?= /* @escapeNotVerified */ $_item->getQty() * 1 ?></td> <td class="item-price"> - <?= /* @escapeNotVerified */ $block->getItemPrice($_item->getOrderItem()) ?> + <?= /* @escapeNotVerified */ $block->getItemPrice($_item) ?> </td> </tr> From 9f41eb6fd9acd74f20138d844059eaf9115041fa Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Wed, 10 Apr 2019 14:23:08 +0300 Subject: [PATCH 447/603] Fix static test. --- app/code/Magento/Review/Block/Adminhtml/Edit/Form.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php b/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php index 8ca6d695113b9..4f7237a0b44be 100644 --- a/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php +++ b/app/code/Magento/Review/Block/Adminhtml/Edit/Form.php @@ -4,11 +4,11 @@ * See COPYING.txt for license details. */ +namespace Magento\Review\Block\Adminhtml\Edit; + /** * Adminhtml Review Edit Form */ -namespace Magento\Review\Block\Adminhtml\Edit; - class Form extends \Magento\Backend\Block\Widget\Form\Generic { /** From 457c52290ac47f24d2e1f96451a9eb383a97aeb0 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 10 Apr 2019 14:39:14 +0300 Subject: [PATCH 448/603] graphQl-579: added test coverage for setting disabled shipping method --- .../Quote/Customer/SetShippingMethodsOnCartTest.php | 8 ++++++++ .../GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php index 9219b5a67022c..0730423589f89 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php @@ -251,6 +251,14 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array }]', 'Could not find a cart with ID "non_existent_masked_id"' ], + 'disabled_shipping_method' => [ + 'cart_id: "cart_id_value", shipping_methods: [{ + cart_address_id: cart_address_id_value + carrier_code: "freeshipping" + method_code: "freeshipping" + }]', + 'Carrier with such method not found: freeshipping, freeshipping' + ] ]; } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php index 2eac002253ff0..862f454194ece 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php @@ -270,6 +270,14 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array }]', 'Could not find a cart with ID "non_existent_masked_id"' ], + 'disabled_shipping_method' => [ + 'cart_id: "cart_id_value", shipping_methods: [{ + cart_address_id: cart_address_id_value + carrier_code: "freeshipping" + method_code: "freeshipping" + }]', + 'Carrier with such method not found: freeshipping, freeshipping' + ], ]; } From 3f7728250fd4a9d07582833dcd9ee47cc1bfadf9 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 10 Apr 2019 14:54:46 +0300 Subject: [PATCH 449/603] graphQl-580: set disabled payment method test coverage --- .../Customer/SetPaymentMethodOnCartTest.php | 28 ++++++++++++++++--- .../Guest/SetPaymentMethodOnCartTest.php | 27 +++++++++++++++--- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php index 73feefe2b094b..81f7c973c7d6e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php @@ -7,10 +7,12 @@ namespace Magento\GraphQl\Quote\Customer; +use Exception; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\Integration\Api\CustomerTokenServiceInterface; use Magento\OfflinePayments\Model\Cashondelivery; use Magento\OfflinePayments\Model\Checkmo; +use Magento\OfflinePayments\Model\Purchaseorder; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -66,7 +68,7 @@ public function testSetPaymentOnCartWithSimpleProduct() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * - * @expectedException \Exception + * @expectedException Exception * @expectedExceptionMessage The shipping address is missing. Set the address and try again. */ public function testSetPaymentOnCartWithSimpleProductAndWithoutAddress() @@ -105,7 +107,7 @@ public function testSetPaymentOnCartWithVirtualProduct() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * - * @expectedException \Exception + * @expectedException Exception * @expectedExceptionMessage The requested Payment Method is not available. */ public function testSetNonExistentPaymentMethod() @@ -120,7 +122,7 @@ public function testSetNonExistentPaymentMethod() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * - * @expectedException \Exception + * @expectedException Exception * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ public function testSetPaymentOnNonExistentCart() @@ -180,7 +182,7 @@ public function testSetPaymentMethodToAnotherCustomerCart() * * @param string $input * @param string $message - * @throws \Exception + * @throws Exception * @dataProvider dataProviderSetPaymentMethodWithoutRequiredParameters */ public function testSetPaymentMethodWithoutRequiredParameters(string $input, string $message) @@ -204,6 +206,24 @@ public function testSetPaymentMethodWithoutRequiredParameters(string $input, str $this->graphQlQuery($query, [], '', $this->getHeaderMap()); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @expectedException Exception + * @expectedExceptionMessage The requested Payment Method is not available. + */ + public function testSetDisabledPaymentOnCart() + { + $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId, $methodCode); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + /** * @return array */ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php index 879d0fd917291..8250765f9dd5d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php @@ -7,9 +7,11 @@ namespace Magento\GraphQl\Quote\Guest; +use Exception; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\OfflinePayments\Model\Cashondelivery; use Magento\OfflinePayments\Model\Checkmo; +use Magento\OfflinePayments\Model\Purchaseorder; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -57,7 +59,7 @@ public function testSetPaymentOnCartWithSimpleProduct() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * - * @expectedException \Exception + * @expectedException Exception * @expectedExceptionMessage The shipping address is missing. Set the address and try again. */ public function testSetPaymentOnCartWithSimpleProductAndWithoutAddress() @@ -94,7 +96,7 @@ public function testSetPaymentOnCartWithVirtualProduct() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * - * @expectedException \Exception + * @expectedException Exception * @expectedExceptionMessage The requested Payment Method is not available. */ public function testSetNonExistentPaymentMethod() @@ -107,7 +109,7 @@ public function testSetNonExistentPaymentMethod() } /** - * @expectedException \Exception + * @expectedException Exception * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ public function testSetPaymentOnNonExistentCart() @@ -149,7 +151,7 @@ public function testSetPaymentMethodToCustomerCart() * @param string $input * @param string $message * @dataProvider dataProviderSetPaymentMethodWithoutRequiredParameters - * @throws \Exception + * @throws Exception */ public function testSetPaymentMethodWithoutRequiredParameters(string $input, string $message) { @@ -216,6 +218,23 @@ public function testReSetPayment() self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); } + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @expectedException Exception + * @expectedExceptionMessage The requested Payment Method is not available. + */ + public function testSetDisabledPaymentOnCart() + { + $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId, $methodCode); + $this->graphQlQuery($query); + } + /** * @param string $maskedQuoteId * @param string $methodCode From ce4af9e43627d6d31acb0cb5a8a841e81a830a82 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Wed, 10 Apr 2019 15:01:12 +0300 Subject: [PATCH 450/603] magento/magento2#20772: Static test fix. --- app/code/Magento/Integration/Model/AdminTokenService.php | 2 +- .../Integration/Test/Unit/Model/AdminTokenServiceTest.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Integration/Model/AdminTokenService.php b/app/code/Magento/Integration/Model/AdminTokenService.php index 084d111a93f85..7726ff979c6d7 100644 --- a/app/code/Magento/Integration/Model/AdminTokenService.php +++ b/app/code/Magento/Integration/Model/AdminTokenService.php @@ -72,7 +72,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function createAdminAccessToken($username, $password) { diff --git a/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php b/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php index ef7cb549cab2b..83efe4074e15f 100644 --- a/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php +++ b/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php @@ -8,6 +8,9 @@ use Magento\Integration\Model\Oauth\Token; +/** + * Test for Magento\Integration\Model\AdminTokenService class. + */ class AdminTokenServiceTest extends \PHPUnit\Framework\TestCase { /** \Magento\Integration\Model\AdminTokenService */ From 8e40ce20f1b604d73fb43fb5a5b985316999d693 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 10 Apr 2019 15:20:50 +0300 Subject: [PATCH 451/603] graphQl-581: set shipping method on an empty cart test coverage --- .../Customer/SetShippingMethodsOnCartTest.php | 33 ++++++++++++++++--- .../Guest/SetShippingMethodsOnCartTest.php | 33 ++++++++++++++++--- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php index 9219b5a67022c..d1b1c66c92ed1 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php @@ -7,6 +7,7 @@ namespace Magento\GraphQl\Quote\Customer; +use Exception; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\GraphQl\Quote\GetQuoteShippingAddressIdByReservedQuoteId; use Magento\Integration\Api\CustomerTokenServiceInterface; @@ -132,7 +133,7 @@ public function testReSetShippingMethod() * @param string $input * @param string $message * @dataProvider dataProviderSetShippingMethodWithWrongParameters - * @throws \Exception + * @throws Exception */ public function testSetShippingMethodWithWrongParameters(string $input, string $message) { @@ -261,7 +262,7 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @expectedException \Exception + * @expectedException Exception * @expectedExceptionMessage You cannot specify multiple shipping methods. */ public function testSetMultipleShippingMethods() @@ -307,7 +308,7 @@ public function testSetMultipleShippingMethods() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * - * @expectedException \Exception + * @expectedException Exception */ public function testSetShippingMethodToGuestCart() { @@ -336,7 +337,7 @@ public function testSetShippingMethodToGuestCart() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * - * @expectedException \Exception + * @expectedException Exception */ public function testSetShippingMethodToAnotherCustomerCart() { @@ -422,6 +423,30 @@ private function getQuery( QUERY; } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * + * @expectedException Exception + * @expectedExceptionMessage The shipping method can't be set for an empty cart. Add an item to cart and try again. + */ + public function testSetShippingMethodOnAnEmptyCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $carrierCode = 'flatrate'; + $methodCode = 'flatrate'; + $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); + + $query = $this->getQuery( + $maskedQuoteId, + $methodCode, + $carrierCode, + $quoteAddressId + ); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + /** * @param string $username * @param string $password diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php index 2eac002253ff0..00d90c5368c47 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php @@ -7,6 +7,7 @@ namespace Magento\GraphQl\Quote\Guest; +use Exception; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\GraphQl\Quote\GetQuoteShippingAddressIdByReservedQuoteId; use Magento\TestFramework\Helper\Bootstrap; @@ -85,7 +86,7 @@ public function testSetShippingMethodOnCartWithSimpleProduct() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_virtual_product.php * - * @expectedException \Exception + * @expectedException Exception * @expectedExceptionMessage The shipping address is missing. Set the address and try again. */ public function testSetShippingMethodOnCartWithSimpleProductAndWithoutAddress() @@ -151,7 +152,7 @@ public function testReSetShippingMethod() * @param string $input * @param string $message * @dataProvider dataProviderSetShippingMethodWithWrongParameters - * @throws \Exception + * @throws Exception */ public function testSetShippingMethodWithWrongParameters(string $input, string $message) { @@ -279,7 +280,7 @@ public function dataProviderSetShippingMethodWithWrongParameters(): array * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @expectedException \Exception + * @expectedException Exception * @expectedExceptionMessage You cannot specify multiple shipping methods. */ public function testSetMultipleShippingMethods() @@ -325,7 +326,7 @@ public function testSetMultipleShippingMethods() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * - * @expectedException \Exception + * @expectedException Exception */ public function testSetShippingMethodToCustomerCart() { @@ -373,6 +374,30 @@ public function testSetShippingMethodIfGuestIsNotOwnerOfAddress() $this->graphQlQuery($query); } + /** + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/quote_with_address.php + * + * @expectedException Exception + * @expectedExceptionMessage The shipping method can't be set for an empty cart. Add an item to cart and try again. + */ + public function testSetShippingMethodOnAnEmptyCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $carrierCode = 'flatrate'; + $methodCode = 'flatrate'; + $quoteAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute('test_quote'); + + $query = $this->getQuery( + $maskedQuoteId, + $methodCode, + $carrierCode, + $quoteAddressId + ); + $this->graphQlQuery($query); + } + /** * @param string $maskedQuoteId * @param string $shippingMethodCode From 4229953752aa4ba48cb9beaa679c2a300d666658 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Wed, 10 Apr 2019 15:33:58 +0300 Subject: [PATCH 452/603] MC-12180: Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie --- .../AdminCreateWidgetActionGroup.xml | 17 +++ .../Catalog/Test/Mftf/Data/WidgetsData.xml | 20 ++++ .../catalog_recently_products-meta.xml | 3 +- .../Test/Mftf/Page/AdminNewWidgetPage.xml | 1 + .../AdminCatalogProductWidgetSection.xml | 15 +++ .../Mftf/Section/StorefrontWidgetsSection.xml | 16 +++ ...listIsPersistedUnderLongTermCookieTest.xml | 105 +++++++++--------- .../AdminCreateWidgetActionGroup.xml | 6 - .../Widget/Test/Mftf/Data/WidgetsData.xml | 20 ---- .../Mftf/Section/AdminNewWidgetSection.xml | 2 - .../Mftf/Section/StorefrontWidgetsSection.xml | 3 - 11 files changed, 122 insertions(+), 86 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Section/AdminCatalogProductWidgetSection.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml new file mode 100644 index 0000000000000..dd66919640a73 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.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="AdminCreateRecentlyProductsWidgetActionGroup" extends="AdminCreateWidgetActionGroup"> + <selectOption selector="{{AdminCatalogProductWidgetSection.productAttributesToShow}}" parameterArray="['Name', 'Image', 'Price']" stepKey="selectAllProductAttributes"/> + <selectOption selector="{{AdminCatalogProductWidgetSection.productButtonsToShow}}" parameterArray="['Add to Cart', 'Add to Compare', 'Add to Wishlist']" stepKey="selectAllProductButtons"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveWidget"/> + <waitForElementVisible selector="{{AdminMessagesSection.successMessage}}" stepKey="waitForSuccessMessageAppears"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been saved" stepKey="seeSuccess"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/WidgetsData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/WidgetsData.xml index 83f0a56c21545..18564ff101fd9 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/WidgetsData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/WidgetsData.xml @@ -12,4 +12,24 @@ <data key="type">Catalog Product Link</data> <data key="template">Product Link Block Template</data> </entity> + <entity name="RecentlyComparedProductsWidget" type="widget"> + <data key="type">Recently Compared Products</data> + <data key="design_theme">Magento Luma</data> + <data key="name" unique="suffix">Recently Compared Products</data> + <array key="store_ids"> + <item>All Store Views</item> + </array> + <data key="display_on">All Pages</data> + <data key="container">Sidebar Additional</data> + </entity> + <entity name="RecentlyViewedProductsWidget" type="widget"> + <data key="type">Recently Viewed Products</data> + <data key="design_theme">Magento Luma</data> + <data key="name" unique="suffix">Recently Viewed Products</data> + <array key="store_ids"> + <item>All Store Views</item> + </array> + <data key="display_on">All Pages</data> + <data key="container">Sidebar Additional</data> + </entity> </entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml b/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml index dad4f5420d461..0fe4f154d5ef5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_recently_products-meta.xml @@ -6,7 +6,8 @@ */ --> <operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataOperation.xsd"> - <operation name="CatalogRecentlyProductsConfiguration" dataType="catalog_recently_products" type="create" auth="adminFormKey" url="/admin/system_config/save/section/catalog/" method="POST"> + <operation name="CatalogRecentlyProductsConfiguration" dataType="catalog_recently_products" type="create" + auth="adminFormKey" url="/admin/system_config/save/section/catalog/" method="POST" successRegex="/messages-message-success/"> <object key="groups" dataType="catalog_recently_products"> <object key="recently_products" dataType="catalog_recently_products"> <object key="fields" dataType="catalog_recently_products"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Page/AdminNewWidgetPage.xml b/app/code/Magento/Catalog/Test/Mftf/Page/AdminNewWidgetPage.xml index e23a503266e33..dd5d5aef08a7c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Page/AdminNewWidgetPage.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Page/AdminNewWidgetPage.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> <page name="AdminNewWidgetPage" url="admin/widget_instance/new/" area="admin" module="Magento_Widget"> <section name="AdminNewWidgetSelectProductPopupSection"/> + <section name="AdminCatalogProductWidgetSection"/> </page> </pages> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCatalogProductWidgetSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCatalogProductWidgetSection.xml new file mode 100644 index 0000000000000..3261db1f63f24 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCatalogProductWidgetSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminCatalogProductWidgetSection"> + <element name="productAttributesToShow" type="multiselect" selector="select[name='parameters[show_attributes][]']"/> + <element name="productButtonsToShow" type="multiselect" selector="select[name='parameters[show_buttons][]']"/> + </section> +</sections> \ No newline at end of file diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml new file mode 100644 index 0000000000000..dbe5ddcc366f1 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontWidgetsSection"> + <element name="widgetRecentlyViewedProductsGrid" type="block" selector=".block.widget.block-viewed-products-grid" timeout="30"/> + <element name="widgetRecentlyComparedProductsGrid" type="block" selector=".block.widget.block-compared-products-grid" timeout="30"/> + <element name="widgetRecentlyOrderedProductsGrid" type="block" selector=".block.block-reorder" timeout="30"/> + </section> +</sections> \ No newline at end of file diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml index b47c5f9571931..220d6b656c384 100644 --- a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml +++ b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml @@ -11,12 +11,13 @@ <test name="StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest"> <annotations> <features value="Persistent"/> - <stories value="Check the widgets is persisted"/> + <stories value="Catalog widget"/> <title value="Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie"/> <description value="Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie"/> <severity value="CRITICAL"/> <testCaseId value="MC-12180"/> <group value="persistent"/> + <group value="widget"/> <skip> <issueId value="MC-15741"/> </skip> @@ -29,7 +30,7 @@ <createData entity="_defaultProduct" stepKey="createSimpleProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <createData entity="SimpleProduct" stepKey="createSimpleProduct2"> + <createData entity="SimpleProduct" stepKey="createSecondSimpleProduct"> <requiredEntity createDataKey="createCategory"/> </createData> <createData entity="Simple_US_Customer" stepKey="createCustomer"/> @@ -48,7 +49,7 @@ <createData entity="DisableSynchronizeWidgetProductsWithBackendStorage" stepKey="disableSynchronizeWidgetProductsWithBackendStorage"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <deleteData createDataKey="createSimpleProduct2" stepKey="deleteSimpleProduct2"/> + <deleteData createDataKey="createSecondSimpleProduct" stepKey="deleteSecondSimpleProduct"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutFromCustomer"/> @@ -62,66 +63,62 @@ </after> <!--Login to storefront from customer--> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="logInFromCustomer"> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginCustomer"> <argument name="Customer" value="$$createCustomer$$"/> </actionGroup> - <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome"/> + <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="checkWelcomeMessage"/> <!--Open the details page of Simple Product 1, Simple Product 2 and add to cart, get to the category--> - <actionGroup ref="AddSimpleProductToCart" stepKey="addProductToCart"> + <actionGroup ref="AddSimpleProductToCart" stepKey="addSimpleProductProductToCart"> <argument name="product" value="$$createSimpleProduct$$"/> </actionGroup> - <actionGroup ref="AddSimpleProductToCart" stepKey="addProductToCart2"> - <argument name="product" value="$$createSimpleProduct2$$"/> + <actionGroup ref="AddSimpleProductToCart" stepKey="addSecondSimpleProductProductToCart"> + <argument name="product" value="$$createSecondSimpleProduct$$"/> </actionGroup> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage3"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageAfterAddedProductToCart"/> <!--The Recently Viewed widget displays Simple Product 1 and Simple Product 2--> <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" stepKey="waitWidgetRecentlyViewedProductsGrid"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct1InRecentlyViewedWidget"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct2.name$$" stepKey="seeProduct2InRecentlyViewedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeSimpleProductInRecentlyViewedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSecondSimpleProduct.name$$" stepKey="seeSecondSimpleProductInRecentlyViewedWidget"/> <!--Add Simple Product 1 and Simple Product 2 to Wishlist--> - <actionGroup ref="StorefrontCustomerAddCategoryProductToWishlistActionGroup" stepKey="addSimpleProduct1ToWishlist"> + <actionGroup ref="StorefrontCustomerAddCategoryProductToWishlistActionGroup" stepKey="addSimpleProductToWishlist"> <argument name="productVar" value="$$createSimpleProduct$$"/> </actionGroup> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage4"/> - <actionGroup ref="StorefrontCustomerAddCategoryProductToWishlistActionGroup" stepKey="addSimpleProduct2ToWishlist"> - <argument name="productVar" value="$$createSimpleProduct2$$"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageAfterProductAddToWishlist"/> + <actionGroup ref="StorefrontCustomerAddCategoryProductToWishlistActionGroup" stepKey="addSecondSimpleProductToWishlist"> + <argument name="productVar" value="$$createSecondSimpleProduct$$"/> </actionGroup> <!--The My Wishlist widget displays Simple Product 1 and Simple Product 2--> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage5"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageToCheckProductsInWishlistSidebar"/> <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProductInWishlistSidebar"> <argument name="productVar" value="$$createSimpleProduct$$"/> </actionGroup> - <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProduct2InWishlistSidebar"> - <argument name="productVar" value="$$createSimpleProduct2$$"/> + <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSecondSimpleProductInWishlistSidebar"> + <argument name="productVar" value="$$createSecondSimpleProduct$$"/> </actionGroup> <!--Add to compare Simple Product and Simple Product 2--> - <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="compareAddSimpleProduct1ToCompare" > + <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="addSimpleProductToCompare" > <argument name="productVar" value="$$createSimpleProduct$$"/> </actionGroup> - <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="compareAddSimpleProduct2ToCompare" > - <argument name="productVar" value="$$createSimpleProduct2$$"/> + <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="addSecondSimpleProductToCompare" > + <argument name="productVar" value="$$createSecondSimpleProduct$$"/> </actionGroup> <!--The Compare Products widget displays Simple Product 1 and Simple Product 2--> - <actionGroup ref="StorefrontCheckCompareSidebarProductActionGroup" stepKey="compareSimpleProduct1InSidebar"> + <actionGroup ref="StorefrontCheckCompareSidebarProductActionGroup" stepKey="checkSimpleProductInCompareSidebar"> <argument name="productVar" value="$$createSimpleProduct$$"/> </actionGroup> - <actionGroup ref="StorefrontCheckCompareSidebarProductActionGroup" stepKey="compareSimpleProduct2InSidebar"> - <argument name="productVar" value="$$createSimpleProduct2$$"/> + <actionGroup ref="StorefrontCheckCompareSidebarProductActionGroup" stepKey="checkSecondSimpleProductInCompareSidebar"> + <argument name="productVar" value="$$createSecondSimpleProduct$$"/> </actionGroup> <!--Click Clear all in the Compare Products widget--> - <waitForElementVisible selector="{{WidgetSection.ClearCompare}}" stepKey="waitForClearCompareBtn"/> - <click selector="{{WidgetSection.ClearCompare}}" stepKey="clickClearCompareBtn"/> - <waitForElementVisible selector="{{WidgetSection.AcceptClear}}" stepKey="waitForAcceptBtn"/> - <click selector="{{WidgetSection.AcceptClear}}" stepKey="acceptClearCompare"/> - <waitForPageLoad stepKey="waitForPageLoad"/> + <actionGroup ref="StorefrontClearCompareActionGroup" stepKey="asd"/> <!--The Recently Compared widget displays Simple Product 1 and Simple Product 2--> <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" stepKey="waitWidgetRecentlyComparedProductsGrid"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyComparedWidget"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct2InRecentlyComparedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyComparedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSecondSimpleProductInRecentlyComparedWidget"/> <!--Place the order--> <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToShoppingCartPage"/> @@ -129,41 +126,41 @@ <argument name="shippingMethod" value="Flat Rate"/> </actionGroup> <!--The Recently Ordered widget displays Simple Product 1 and Simple Product 2--> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage6"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageToCheckProductsInRecentlyOrderedWidget"/> <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" stepKey="waitWidgetRecentlyOrderedProductsGrid"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyOrderedWidget"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct2InRecentlyOrderedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyOrderedWidget"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSecondSimpleProductInRecentlyOrderedWidget"/> <!--Sign out and check that widgets persist the information about the items--> - <actionGroup ref="StorefrontSignOutActionGroup" stepKey="storefrontSignOut"/> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage7"/> - <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome2"/> - <seeElement selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="checkLinkNotYoy"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct1InRecentlyViewedWidget2"/> - <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProductInWishlistSidebar2"> + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="logoutFromCustomerToCheckThatWidgetsPersist"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageAfterLogoutFromCustomer"/> + <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="checkWelcomeMessageAfterLogoutFromCustomer"/> + <seeElement selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="checkLinkNotYouAfterLogoutFromCustomer"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyViewedWidgetAfterLogout"/> + <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProductInWishlistSidebarAfterLogout"> <argument name="productVar" value="$$createSimpleProduct$$"/> </actionGroup> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyComparedWidget2"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyOrderedWidget2"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyComparedWidgetAfterLogout"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyOrderedWidgetAfterLogout"/> <!--Click the *Not you?* link and check the price for Simple Product--> - <click selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="clickNext"/> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage8"/> - <see userInput="Default welcome msg!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome3"/> - <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProduct1InRecentlyViewedWidget"/> - <dontSee selector="{{StorefrontCustomerWishlistSidebarSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="dontSeeProduct1InWishlistWidget"/> + <click selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="clickLinkNotYou"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageAfterClickNotYou"/> + <see userInput="Default welcome msg!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="checkWelcomeMessageAfterClickLinkNotYou"/> + <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProductInRecentlyViewedWidget"/> + <dontSee selector="{{StorefrontCustomerWishlistSidebarSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="dontSeeProductInWishlistWidget"/> <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProductInRecentlyComparedWidget"/> <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProductInRecentlyOrderedWidget"/> <!--Login to storefront from customer again--> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="logInFromCustomer2"> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="logInFromCustomerAfterClearLongTermCookie"> <argument name="Customer" value="$$createCustomer$$"/> </actionGroup> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage9"/> - <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome4"/> - <waitForElementVisible selector="{{StorefrontCustomerWishlistSidebarSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="assertWishlistSidebarProductName"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct1InRecentlyViewedWidget3"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyComparedWidget3"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductInRecentlyOrderedWidget3"/> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageToCheckWidgets"/> + <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="checkWelcomeMessageAfterLogin"/> + <waitForElementVisible selector="{{StorefrontCustomerWishlistSidebarSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="checkSimpleProductNameInWishlistSidebarAfterLogin"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyViewedWidgetAfterLogin"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyComparedWidgetAfterLogin"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyOrderedWidgetAfterLogin"/> </test> </tests> diff --git a/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml b/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml index 5d2b894b86438..969ab58b04876 100644 --- a/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml +++ b/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml @@ -78,10 +78,4 @@ <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveWidget"/> <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been saved" stepKey="seeSuccess"/> </actionGroup> - <actionGroup name="AdminCreateRecentlyProductsWidgetActionGroup" extends="AdminCreateWidgetActionGroup"> - <selectOption selector="{{AdminNewWidgetSection.productAttributesToShow}}" parameterArray="['Name', 'Image', 'Price']" stepKey="selectAllProductAttributes"/> - <selectOption selector="{{AdminNewWidgetSection.productButtonsToShow}}" parameterArray="['Add to Cart', 'Add to Compare', 'Add to Wishlist']" stepKey="selectAllProductButtons"/> - <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveWidget"/> - <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been saved" stepKey="seeSuccess"/> - </actionGroup> </actionGroups> diff --git a/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml b/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml index 370077f6feefa..27222298408de 100644 --- a/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml +++ b/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml @@ -32,24 +32,4 @@ <data key="display_mode">Cart Price Rule Related</data> <data key="restrict_type">Header</data> </entity> - <entity name="RecentlyComparedProductsWidget" type="widget"> - <data key="type">Recently Compared Products</data> - <data key="design_theme">Magento Luma</data> - <data key="name" unique="suffix">Recently Compared Products</data> - <array key="store_ids"> - <item>All Store Views</item> - </array> - <data key="display_on">All Pages</data> - <data key="container">Sidebar Additional</data> - </entity> - <entity name="RecentlyViewedProductsWidget" type="widget"> - <data key="type">Recently Viewed Products</data> - <data key="design_theme">Magento Luma</data> - <data key="name" unique="suffix">Recently Viewed Products</data> - <array key="store_ids"> - <item>All Store Views</item> - </array> - <data key="display_on">All Pages</data> - <data key="container">Sidebar Additional</data> - </entity> </entities> diff --git a/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml b/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml index 8abd8cb142016..eebd6c10b5085 100644 --- a/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml +++ b/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml @@ -35,7 +35,5 @@ <element name="displayMode" type="select" selector="select[id*='display_mode']"/> <element name="restrictTypes" type="select" selector="select[id*='types']"/> <element name="saveAndContinue" type="button" selector="#save_and_edit_button" timeout="30"/> - <element name="productAttributesToShow" type="multiselect" selector="select[name='parameters[show_attributes][]']"/> - <element name="productButtonsToShow" type="multiselect" selector="select[name='parameters[show_buttons][]']"/> </section> </sections> diff --git a/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml b/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml index cf6bfc484cc57..0e2f6cec73a92 100644 --- a/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml +++ b/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml @@ -11,8 +11,5 @@ <section name="StorefrontWidgetsSection"> <element name="widgetProductsGrid" type="block" selector=".block.widget.block-products-list.grid"/> <element name="widgetProductName" type="text" selector=".product-item-name"/> - <element name="widgetRecentlyViewedProductsGrid" type="block" selector=".block.widget.block-viewed-products-grid" timeout="30"/> - <element name="widgetRecentlyComparedProductsGrid" type="block" selector=".block.widget.block-compared-products-grid" timeout="30"/> - <element name="widgetRecentlyOrderedProductsGrid" type="block" selector=".block.block-reorder" timeout="30"/> </section> </sections> From 601e205e10f89640de535b2f0482a773b98afa93 Mon Sep 17 00:00:00 2001 From: Vova Yatsyuk <vova.yatsyuk@gmail.com> Date: Wed, 10 Apr 2019 15:46:40 +0300 Subject: [PATCH 453/603] Use 'lib-css' utility --- .../web/css/source/module/checkout/_tooltip.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less index abc990c56f651..ddf33de6820e7 100644 --- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less @@ -173,10 +173,10 @@ width: 0; } .field-tooltip .field-tooltip-content::before { - border-bottom-color: @checkout-tooltip-content__border-color; + .lib-css(border-bottom-color, @checkout-tooltip-content__border-color); } .field-tooltip .field-tooltip-content::after { - border-bottom-color: @checkout-tooltip-content__background-color; + .lib-css(border-bottom-color, @checkout-tooltip-content__background-color); top: 1px; } } From 921f7b90bbc32e2759bffdb93529b864b479f41b Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Wed, 10 Apr 2019 16:43:51 +0300 Subject: [PATCH 454/603] magento/magento2#20832: MFTF test fix. --- .../Test/Mftf/Section/StorefrontPanelHeaderSection.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml index 1955c6a417ba9..a06b099220b56 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml @@ -12,8 +12,8 @@ <element name="WelcomeMessage" type="text" selector=".greet.welcome span"/> <element name="createAnAccountLink" type="select" selector=".panel.header li:nth-child(3)" timeout="30"/> <element name="notYouLink" type="button" selector=".greet.welcome span a"/> - <element name="customerWelcome" type="text" selector=".panel.header .customer-welcome"/> - <element name="customerWelcomeMenu" type="text" selector=".panel.header .customer-welcome .customer-menu"/> - <element name="customerLogoutLink" type="text" selector=".panel.header .customer-welcome .customer-menu .authorization-link a" timeout="30"/> + <element name="customerWelcome" type="text" selector=".panel.header .greet.welcome"/> + <element name="customerWelcomeMenu" type="text" selector=".panel.header .greet.welcome .customer-menu"/> + <element name="customerLogoutLink" type="text" selector=".panel.header .greet.welcome .customer-menu .authorization-link a" timeout="30"/> </section> </sections> From ec2c6ca7df68de9aaccecfb899b102a2a3eaa631 Mon Sep 17 00:00:00 2001 From: Ryan Palmer <ryan.palmer@hub-mdp.co.uk> Date: Wed, 10 Apr 2019 10:28:51 +0100 Subject: [PATCH 455/603] Prevented /Magento/Sales/Model/Service/InvoiceService.php incorrectly discarding simple items when bundle items are mixed in a call to prepareInvoice without any qtys specified Renamed emptyQtys to isQtysEmpty --- app/code/Magento/Sales/Model/Service/InvoiceService.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Service/InvoiceService.php b/app/code/Magento/Sales/Model/Service/InvoiceService.php index 02242e92c8bf5..18efeba726c1b 100644 --- a/app/code/Magento/Sales/Model/Service/InvoiceService.php +++ b/app/code/Magento/Sales/Model/Service/InvoiceService.php @@ -149,6 +149,7 @@ public function setVoid($id) */ public function prepareInvoice(Order $order, array $qtys = []) { + $isQtysEmpty = empty($qtys); $invoice = $this->orderConverter->toInvoice($order); $totalQty = 0; $qtys = $this->prepareItemsQty($order, $qtys); @@ -161,7 +162,7 @@ public function prepareInvoice(Order $order, array $qtys = []) $qty = (double) $qtys[$orderItem->getId()]; } elseif ($orderItem->isDummy()) { $qty = $orderItem->getQtyOrdered() ? $orderItem->getQtyOrdered() : 1; - } elseif (empty($qtys)) { + } elseif ($isQtysEmpty) { $qty = $orderItem->getQtyToInvoice(); } else { $qty = 0; From ad6581211a31bb3d8b69f400cb97f14bf582d307 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Wed, 10 Apr 2019 17:05:02 +0300 Subject: [PATCH 456/603] magento/magento2#21821: Static test fix. --- .../backend/web/css/source/forms/fields/_field-tooltips.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/fields/_field-tooltips.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/fields/_field-tooltips.less index e5891e39648fc..befd27fa57df6 100755 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/fields/_field-tooltips.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/fields/_field-tooltips.less @@ -22,7 +22,7 @@ @field-tooltip-content__width: 32rem; @field-tooltip-content__z-index: 1; -@field-tooltip-action__margin-left: 0rem; +@field-tooltip-action__margin-left: 0; // // Form Fields From f0be69a9c195bee0acb8d0117d499aa1db0b175b Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 10 Apr 2019 13:30:07 -0500 Subject: [PATCH 457/603] GraphQL-382: Test coverage of Adding simple/virtual product to shopping cart --- .../CatalogInventory/AddProductToCartTest.php | 52 +++--- .../AddConfigurableProductToCartTest.php | 63 ++------ ...pleProductWithCustomOptionsToCartTest.php} | 152 ++---------------- ...ualProductWithCustomOptionsToCartTest.php} | 42 ++--- .../Guest/AddSimpleProductToCartTest.php | 102 ++++++++++++ .../_files/product_simple_with_options.php | 1 + .../product_simple_with_options_rollback.php | 3 +- .../Catalog/_files/product_virtual.php | 5 +- .../_files/product_virtual_rollback.php | 3 +- .../_files/product_virtual_with_options.php | 1 + .../product_virtual_with_options_rollback.php | 2 +- 11 files changed, 168 insertions(+), 258 deletions(-) rename dev/tests/api-functional/testsuite/Magento/GraphQl/{Quote => ConfigurableProduct}/AddConfigurableProductToCartTest.php (60%) rename dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/{AddSimpleProductToCartTest.php => AddSimpleProductWithCustomOptionsToCartTest.php} (56%) rename dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/{AddVirtualProductToCartTest.php => AddVirtualProductWithCustomOptionsToCartTest.php} (81%) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 17c2af8dc59d0..86e71d9914fe3 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -7,28 +7,19 @@ namespace Magento\GraphQl\CatalogInventory; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +/** + * Add simple product to cart testcases related to inventory + */ class AddProductToCartTest extends GraphQlAbstract { /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var QuoteFactory - */ - private $quoteFactory; - - /** - * @var QuoteIdToMaskedQuoteIdInterface + * @var GetMaskedQuoteIdByReservedOrderId */ - private $quoteIdToMaskedId; + private $getMaskedQuoteIdByReservedOrderId; /** * @inheritdoc @@ -36,9 +27,7 @@ class AddProductToCartTest extends GraphQlAbstract protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); } /** @@ -51,11 +40,10 @@ public function testAddProductIfQuantityIsNotAvailable() { $sku = 'simple'; $qty = 200; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $maskedQuoteId = $this->getMaskedQuoteId(); - $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->graphQlQuery($query); - self::fail('Should be "The requested qty is not available" error message.'); } /** @@ -71,22 +59,26 @@ public function testAddMoreProductsThatAllowed() $sku = 'custom-design-simple-product'; $qty = 7; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $maskedQuoteId = $this->getMaskedQuoteId(); - $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->graphQlQuery($query); - self::fail('Should be "The most you may purchase is 5." error message.'); } /** - * @return string + * @magentoApiDataFixture Magento/Catalog/_files/products.php + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + * @expectedException \Exception + * @expectedExceptionMessage Please enter a number greater than 0 in this field. */ - public function getMaskedQuoteId() : string + public function testAddSimpleProductToCartWithNegativeQty() { - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id'); + $sku = 'simple'; + $qty = -2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - return $this->quoteIdToMaskedId->execute((int)$quote->getId()); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $this->graphQlQuery($query); } /** @@ -95,7 +87,7 @@ public function getMaskedQuoteId() : string * @param int $qty * @return string */ - public function getAddSimpleProductQuery(string $maskedQuoteId, string $sku, int $qty) : string + private function getQuery(string $maskedQuoteId, string $sku, int $qty) : string { return <<<QUERY mutation { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddConfigurableProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php similarity index 60% rename from dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddConfigurableProductToCartTest.php rename to dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php index b3f16c8734203..e4ae59cc0d281 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddConfigurableProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php @@ -5,30 +5,21 @@ */ declare(strict_types=1); -namespace Magento\GraphQl\Quote; +namespace Magento\GraphQl\ConfigurableProduct; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; -use Magento\Quote\Model\Quote; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +/** + * Add configurable product to cart testcases + */ class AddConfigurableProductToCartTest extends GraphQlAbstract { /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var Quote + * @var GetMaskedQuoteIdByReservedOrderId */ - private $quote; - - /** - * @var QuoteIdToMaskedQuoteIdInterface - */ - private $quoteIdToMaskedId; + private $getMaskedQuoteIdByReservedOrderId; /** * @inheritdoc @@ -36,9 +27,7 @@ class AddConfigurableProductToCartTest extends GraphQlAbstract protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quote = $objectManager->create(Quote::class); - $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); } /** @@ -49,12 +38,11 @@ public function testAddConfigurableProductToCart() { $variantSku = 'simple_41'; $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $maskedQuoteId = $this->getMaskedQuoteId(); - - $query = $this->getAddConfigurableProductMutationQuery($maskedQuoteId, $variantSku, $qty); - + $query = $this->getQuery($maskedQuoteId, $variantSku, $qty); $response = $this->graphQlQuery($query); + $cartItems = $response['addConfigurableProductsToCart']['cart']['items']; self::assertEquals($qty, $cartItems[0]['qty']); self::assertEquals($variantSku, $cartItems[0]['product']['sku']); @@ -70,10 +58,9 @@ public function testAddProductIfQuantityIsNotAvailable() { $variantSku = 'simple_41'; $qty = 200; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $maskedQuoteId = $this->getMaskedQuoteId(); - $query = $this->getAddConfigurableProductMutationQuery($maskedQuoteId, $variantSku, $qty); - + $query = $this->getQuery($maskedQuoteId, $variantSku, $qty); $this->graphQlQuery($query); } @@ -87,35 +74,19 @@ public function testAddOutOfStockProduct() { $variantSku = 'simple_1010'; $qty = 1; - $maskedQuoteId = $this->getMaskedQuoteId(); - $query = $this->getAddConfigurableProductMutationQuery($maskedQuoteId, $variantSku, $qty); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); + $query = $this->getQuery($maskedQuoteId, $variantSku, $qty); $this->graphQlQuery($query); } - /** - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php - * @return string - * @throws \Magento\Framework\Exception\NoSuchEntityException - */ - private function getMaskedQuoteId() - { - $this->quoteResource->load( - $this->quote, - 'test_order_1', - 'reserved_order_id' - ); - return $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - } - /** * @param string $maskedQuoteId - * @param string $sku + * @param string $variantSku * @param int $qty - * * @return string */ - private function getAddConfigurableProductMutationQuery(string $maskedQuoteId, string $variantSku, int $qty): string + private function getQuery(string $maskedQuoteId, string $variantSku, int $qty): string { return <<<QUERY mutation { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php similarity index 56% rename from dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php rename to dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php index e6a5395b0d7b3..6da1b2c9b54c9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php @@ -8,28 +8,18 @@ namespace Magento\GraphQl\Quote; use Magento\Catalog\Api\ProductCustomOptionRepositoryInterface; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; -class AddSimpleProductToCartTest extends GraphQlAbstract +/** + * Add simple product with custom options to cart testcases + */ +class AddSimpleProductWithCustomOptionsToCartTest extends GraphQlAbstract { /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var QuoteFactory - */ - private $quoteFactory; - - /** - * @var QuoteIdToMaskedQuoteIdInterface + * @var GetMaskedQuoteIdByReservedOrderId */ - private $quoteIdToMaskedId; + private $getMaskedQuoteIdByReservedOrderId; /** * @var ProductCustomOptionRepositoryInterface @@ -42,9 +32,7 @@ class AddSimpleProductToCartTest extends GraphQlAbstract protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); $this->productCustomOptionsRepository = $objectManager->get(ProductCustomOptionRepositoryInterface::class); } @@ -59,14 +47,13 @@ public function testAddSimpleProductWithOptions() { $sku = 'simple'; $qty = 1; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $customOptionsValues = $this->getCustomOptionsValuesForQuery($sku); /* Generate customizable options fragment for GraphQl request */ $queryCustomizableOptions = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues)); - $maskedQuoteId = $this->getMaskedQuoteId(); - $query = <<<QUERY mutation { addSimpleProductsToCart( @@ -114,126 +101,6 @@ public function testAddSimpleProductWithOptions() } } - /** - * @magentoApiDataFixture Magento/Catalog/_files/products.php - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php - */ - public function testAddSimpleProductToCart() - { - $sku = 'simple'; - $qty = 2; - $maskedQuoteId = $this->getMaskedQuoteId(); - - $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); - $response = $this->graphQlQuery($query); - self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); - - self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['qty']); - self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); - } - - /** - * @magentoApiDataFixture Magento/Catalog/_files/products.php - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php - * @expectedException \Exception - * @expectedExceptionMessage Please enter a number greater than 0 in this field. - */ - public function testAddSimpleProductToCartWithNegativeQty() - { - $sku = 'simple'; - $qty = -2; - $maskedQuoteId = $this->getMaskedQuoteId(); - - $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); - $this->graphQlQuery($query); - } - - /** - * @return string - */ - private function getMaskedQuoteId() : string - { - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id'); - - return $this->quoteIdToMaskedId->execute((int)$quote->getId()); - } - - /** - * @param string $maskedQuoteId - * @param string $sku - * @param int $qty - * @return string - */ - public function getAddSimpleProductQuery(string $maskedQuoteId, string $sku, int $qty): string - { - return <<<QUERY -mutation { - addSimpleProductsToCart( - input: { - cart_id: "{$maskedQuoteId}" - cartItems: [ - { - data: { - qty: $qty - sku: "$sku" - } - } - ] - } - ) { - cart { - items { - qty - product { - sku - } - } - } - } -} -QUERY; - } - - /** - * @magentoApiDataFixture Magento/Catalog/_files/products.php - * @expectedException \Exception - * @expectedExceptionMessage Could not find a cart with ID "wrong_cart_hash" - */ - public function testAddProductWithWrongCartHash() - { - $sku = 'simple'; - $qty = 1; - - $maskedQuoteId = 'wrong_cart_hash'; - - $query = <<<QUERY -mutation { - addSimpleProductsToCart( - input: { - cart_id: "{$maskedQuoteId}" - cartItems: [ - { - data: { - qty: $qty - sku: "$sku" - } - } - ] - } - ) { - cart { - items { - qty - } - } - } -} -QUERY; - - $this->graphQlQuery($query); - } - /** * Test adding a simple product with empty values for required options * @@ -244,8 +111,7 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() { $sku = 'simple'; $qty = 1; - - $maskedQuoteId = $this->getMaskedQuoteId(); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $query = <<<QUERY mutation { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php similarity index 81% rename from dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductToCartTest.php rename to dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php index da4e6de2d0aa6..1e1ee91336107 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php @@ -7,28 +7,19 @@ namespace Magento\GraphQl\Quote; -use Magento\Quote\Model\QuoteFactory; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\Catalog\Api\ProductCustomOptionRepositoryInterface; -class AddVirtualProductToCartTest extends GraphQlAbstract +/** + * Add virtual product with custom options to cart testcases + */ +class AddVirtualProductWithCustomOptionsToCartTest extends GraphQlAbstract { /** - * @var QuoteFactory - */ - private $quoteFactory; - /** - * @var QuoteResource + * @var GetMaskedQuoteIdByReservedOrderId */ - private $quoteResource; - - /** - * @var QuoteIdToMaskedQuoteIdInterface - */ - private $quoteIdToMaskedId; + private $getMaskedQuoteIdByReservedOrderId; /** * @var ProductCustomOptionRepositoryInterface @@ -41,9 +32,7 @@ class AddVirtualProductToCartTest extends GraphQlAbstract protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); $this->productCustomOptionsRepository = $objectManager->get(ProductCustomOptionRepositoryInterface::class); } @@ -58,14 +47,13 @@ public function testAddVirtualProductWithOptions() { $sku = 'virtual'; $qty = 1; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $customOptionsValues = $this->getCustomOptionsValuesForQuery($sku); /* Generate customizable options fragment for GraphQl request */ $queryCustomizableOptions = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues)); - $maskedQuoteId = $this->getMaskedQuoteId(); - $query = <<<QUERY mutation { addVirtualProductsToCart( @@ -123,8 +111,7 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() { $sku = 'virtual'; $qty = 1; - - $maskedQuoteId = $this->getMaskedQuoteId(); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $query = <<<QUERY mutation { @@ -194,15 +181,4 @@ private function getCustomOptionsValuesForQuery(string $sku): array return $customOptionsValues; } - - /** - * @return string - */ - public function getMaskedQuoteId() : string - { - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id'); - - return $this->quoteIdToMaskedId->execute((int)$quote->getId()); - } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php new file mode 100644 index 0000000000000..3270449f3e8dd --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php @@ -0,0 +1,102 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Add simple product to cart testcases + */ +class AddSimpleProductToCartTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products.php + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + */ + public function testAddSimpleProductToCart() + { + $sku = 'simple'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); + + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $response = $this->graphQlQuery($query); + self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); + + self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" + */ + public function testAddProductToNonExistentCart() + { + $sku = 'simple'; + $qty = 1; + $maskedQuoteId = 'non_existent_masked_id'; + + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $this->graphQlQuery($query); + } + + /** + * @param string $maskedQuoteId + * @param string $sku + * @param int $qty + * @return string + */ + private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + { + return <<<QUERY +mutation { + addSimpleProductsToCart( + input: { + cart_id: "{$maskedQuoteId}" + cartItems: [ + { + data: { + qty: $qty + sku: "$sku" + } + } + ] + } + ) { + cart { + items { + qty + product { + sku + } + } + } + } +} +QUERY; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options.php index fa8046fef3975..a401db8eb2bf7 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options_rollback.php index 2d783a6d07522..8863da1cd2782 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_options_rollback.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); /** @var \Magento\Framework\Registry $registry */ $registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class); @@ -18,8 +19,6 @@ $repository->delete($product); } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { //Entity already deleted -} catch (\Magento\Framework\Exception\StateException $e) { - } $registry->unregister('isSecureArea'); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php index 8f42436f08a31..838ae2b9a2aa6 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php @@ -3,12 +3,13 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); -use Magento\Catalog\Model\ProductFactory; +use Magento\Catalog\Api\Data\ProductInterfaceFactory; use Magento\TestFramework\Helper\Bootstrap; use Magento\Catalog\Model\ResourceModel\Product as ProductResource; -$productFactory = Bootstrap::getObjectManager()->get(ProductFactory::class); +$productFactory = Bootstrap::getObjectManager()->get(ProductInterfaceFactory::class); $product = $productFactory->create(); $product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL) ->setId(21) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_rollback.php index 84039adc416aa..f5568ced2c96a 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_rollback.php @@ -3,6 +3,7 @@ * 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; @@ -15,7 +16,7 @@ $registry->register('isSecureArea', true); $productRepository = Bootstrap::getObjectManager() - ->create(ProductRepositoryInterface::class); + ->get(ProductRepositoryInterface::class); try { $product = $productRepository->get('virtual-product', false, null, true); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options.php index c07eb0f35b0fd..c1f981cefa646 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options_rollback.php index 070e2890df413..f46cdc13d3263 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual_with_options_rollback.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); /** @var \Magento\Framework\Registry $registry */ $registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class); @@ -18,7 +19,6 @@ $repository->delete($product); } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { //Entity already deleted -} catch (\Magento\Framework\Exception\StateException $e) { } $registry->unregister('isSecureArea'); From 8434d74abd6393d2cb4ad45eff6c9ec292f4dc71 Mon Sep 17 00:00:00 2001 From: David Alger <davidmalger@gmail.com> Date: Wed, 10 Apr 2019 15:41:25 -0500 Subject: [PATCH 458/603] Fixed #15090: Update Magento_Config module to allow admin/url/use_custom in env.php --- .../Magento/Config/Model/Config/Backend/Admin/Usecustom.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php b/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php index 9a483de6a695b..d12569eebe5b2 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php +++ b/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php @@ -56,8 +56,9 @@ public function beforeSave() { $value = $this->getValue(); if ($value == 1) { - $customUrl = $this->getData('groups/url/fields/custom/value'); - if (empty($customUrl)) { + $customUrlField = $this->getData('groups/url/fields/custom/value'); + $customUrlConfig = $this->_config->getValue('admin/url/custom'); + if (empty($customUrlField) && empty($customUrlConfig)) { throw new \Magento\Framework\Exception\LocalizedException(__('Please specify the admin custom URL.')); } } From a3cdeb7c89c4083c662c630076addba15e76a6c5 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Thu, 11 Apr 2019 11:24:44 +0300 Subject: [PATCH 459/603] MC-12180: Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie --- ...efrontAssertProductInWidgetActionGroup.xml | 37 +++++++++++ ...listIsPersistedUnderLongTermCookieTest.xml | 61 +++++++++++++------ 2 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductInWidgetActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductInWidgetActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductInWidgetActionGroup.xml new file mode 100644 index 0000000000000..c25b73bab21ae --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductInWidgetActionGroup.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Check the product in recently viewed widget --> + <actionGroup name="StorefrontAssertProductInRecentlyViewedWidgetActionGroup"> + <arguments> + <argument name="product"/> + </arguments> + <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" stepKey="waitWidgetRecentlyViewedProductsGrid"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="{{product.name}}" stepKey="seeProductInRecentlyViewedWidget"/> + </actionGroup> + + <!-- Check the product in recently compared widget --> + <actionGroup name="StorefrontAssertProductInRecentlyComparedWidgetActionGroup"> + <arguments> + <argument name="product"/> + </arguments> + <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" stepKey="waitWidgetRecentlyComparedProductsGrid"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="{{product.name}}" stepKey="seeProductInRecentlyComparedWidget"/> + </actionGroup> + + <!-- Check the product in recently ordered widget --> + <actionGroup name="StorefrontAssertProductInRecentlyOrderedWidgetActionGroup"> + <arguments> + <argument name="product"/> + </arguments> + <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" stepKey="waitWidgetRecentlyOrderedProductsGrid"/> + <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="{{product.name}}" stepKey="seeProductInRecentlyOrderedWidget"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml index 220d6b656c384..dc6f87bef0ba8 100644 --- a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml +++ b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml @@ -18,6 +18,7 @@ <testCaseId value="MC-12180"/> <group value="persistent"/> <group value="widget"/> + <group value="catalog_widget"/> <skip> <issueId value="MC-15741"/> </skip> @@ -77,9 +78,12 @@ </actionGroup> <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageAfterAddedProductToCart"/> <!--The Recently Viewed widget displays Simple Product 1 and Simple Product 2--> - <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" stepKey="waitWidgetRecentlyViewedProductsGrid"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="seeSimpleProductInRecentlyViewedWidget"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSecondSimpleProduct.name$$" stepKey="seeSecondSimpleProductInRecentlyViewedWidget"/> + <actionGroup ref="StorefrontAssertProductInRecentlyViewedWidgetActionGroup" stepKey="seeSimpleProductInRecentlyViewedWidget"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductInRecentlyViewedWidgetActionGroup" stepKey="seeSecondSimpleProductInRecentlyViewedWidget"> + <argument name="product" value="$$createSecondSimpleProduct$$"/> + </actionGroup> <!--Add Simple Product 1 and Simple Product 2 to Wishlist--> <actionGroup ref="StorefrontCustomerAddCategoryProductToWishlistActionGroup" stepKey="addSimpleProductToWishlist"> @@ -114,11 +118,14 @@ </actionGroup> <!--Click Clear all in the Compare Products widget--> - <actionGroup ref="StorefrontClearCompareActionGroup" stepKey="asd"/> + <actionGroup ref="StorefrontClearCompareActionGroup" stepKey="clearCompareList"/> <!--The Recently Compared widget displays Simple Product 1 and Simple Product 2--> - <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" stepKey="waitWidgetRecentlyComparedProductsGrid"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyComparedWidget"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSecondSimpleProductInRecentlyComparedWidget"/> + <actionGroup ref="StorefrontAssertProductInRecentlyComparedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyComparedWidget"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductInRecentlyComparedWidgetActionGroup" stepKey="checkSecondSimpleProductInRecentlyComparedWidget"> + <argument name="product" value="$$createSecondSimpleProduct$$"/> + </actionGroup> <!--Place the order--> <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToShoppingCartPage"/> @@ -127,24 +134,35 @@ </actionGroup> <!--The Recently Ordered widget displays Simple Product 1 and Simple Product 2--> <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageToCheckProductsInRecentlyOrderedWidget"/> - <waitForElementVisible selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" stepKey="waitWidgetRecentlyOrderedProductsGrid"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyOrderedWidget"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSecondSimpleProductInRecentlyOrderedWidget"/> + <actionGroup ref="StorefrontAssertProductInRecentlyOrderedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyOrderedWidget"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductInRecentlyOrderedWidgetActionGroup" stepKey="checkSecondSimpleProductInRecentlyOrderedWidget"> + <argument name="product" value="$$createSecondSimpleProduct$$"/> + </actionGroup> <!--Sign out and check that widgets persist the information about the items--> <actionGroup ref="StorefrontSignOutActionGroup" stepKey="logoutFromCustomerToCheckThatWidgetsPersist"/> <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageAfterLogoutFromCustomer"/> <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="checkWelcomeMessageAfterLogoutFromCustomer"/> <seeElement selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="checkLinkNotYouAfterLogoutFromCustomer"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyViewedWidgetAfterLogout"/> + + <actionGroup ref="StorefrontAssertProductInRecentlyViewedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyViewedWidgetAfterLogout"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProductInWishlistSidebarAfterLogout"> <argument name="productVar" value="$$createSimpleProduct$$"/> </actionGroup> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyComparedWidgetAfterLogout"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyOrderedWidgetAfterLogout"/> + <actionGroup ref="StorefrontAssertProductInRecentlyComparedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyComparedWidgetAfterLogout"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductInRecentlyOrderedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyOrderedWidgetAfterLogout"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> <!--Click the *Not you?* link and check the price for Simple Product--> <click selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="clickLinkNotYou"/> + <waitForPageLoad stepKey="waitForPageLoadAfterClickLinkNotYou"/> <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageAfterClickNotYou"/> <see userInput="Default welcome msg!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="checkWelcomeMessageAfterClickLinkNotYou"/> <dontSee selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="dontSeeProductInRecentlyViewedWidget"/> @@ -158,9 +176,18 @@ </actionGroup> <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="openCategoryPageToCheckWidgets"/> <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="checkWelcomeMessageAfterLogin"/> - <waitForElementVisible selector="{{StorefrontCustomerWishlistSidebarSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="checkSimpleProductNameInWishlistSidebarAfterLogin"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyViewedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyViewedWidgetAfterLogin"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyComparedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyComparedWidgetAfterLogin"/> - <see selector="{{StorefrontWidgetsSection.widgetRecentlyOrderedProductsGrid}}" userInput="$$createSimpleProduct.name$$" stepKey="checkSimpleProductInRecentlyOrderedWidgetAfterLogin"/> + + <actionGroup ref="StorefrontCustomerCheckProductInWishlistSidebar" stepKey="checkSimpleProductNameInWishlistSidebarAfterLogin"> + <argument name="productVar" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductInRecentlyViewedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyViewedWidgetAfterLogin"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductInRecentlyComparedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyComparedWidgetAfterLogin"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductInRecentlyOrderedWidgetActionGroup" stepKey="checkSimpleProductInRecentlyOrderedWidgetAfterLogin"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> </test> </tests> From 9e8519de2367581ff26dc76432e88a7ccbf987d8 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Thu, 11 Apr 2019 12:24:00 +0200 Subject: [PATCH 460/603] Tests refactoring based on new fixtures principle --- .../GraphQl/Quote/Customer/CartTotalsTest.php | 47 ++++++++----- .../GraphQl/Quote/Guest/CartTotalsTest.php | 53 +++++++++------ .../_files/product_simple_with_tax.php | 45 ------------- .../product_simple_with_tax_rollback.php | 8 --- .../_files/quote_with_address_guest.php | 61 ----------------- .../quote_with_address_guest_rollback.php | 21 ------ .../_files/quote_with_customer_no_address.php | 48 ------------- ...uote_with_customer_no_address_rollback.php | 22 ------ .../_files/quote_with_tax_customer.php | 67 ------------------- .../quote_with_tax_customer_rollback.php | 22 ------ .../Checkout/_files/quote_with_tax_guest.php | 63 ----------------- .../_files/quote_with_tax_guest_rollback.php | 21 ------ .../_files/customer_with_tax_group.php | 10 --- .../customer_with_tax_group_rollback.php | 7 -- .../_files/apply_tax_for_simple_product.php | 26 +++++++ .../Tax/_files/tax_rule_for_region_1.php | 53 +++++++++++++++ .../_files/tax_rule_for_region_1_rollback.php | 38 +++++++++++ 17 files changed, 181 insertions(+), 431 deletions(-) delete mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_tax.php delete mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_tax_rollback.php delete mode 100644 dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_address_guest.php delete mode 100644 dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_address_guest_rollback.php delete mode 100644 dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_customer_no_address.php delete mode 100644 dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_customer_no_address_rollback.php delete mode 100644 dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_customer.php delete mode 100644 dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_customer_rollback.php delete mode 100644 dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_guest.php delete mode 100644 dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_guest_rollback.php delete mode 100644 dev/tests/integration/testsuite/Magento/Customer/_files/customer_with_tax_group.php delete mode 100644 dev/tests/integration/testsuite/Magento/Customer/_files/customer_with_tax_group_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Tax/_files/tax_rule_for_region_1_rollback.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php index 8dc6650b68f91..4a25e9331d86e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php @@ -49,34 +49,46 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_tax_customer.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ public function testGetCartTotalsWithTaxApplied() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_tax'); + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_quote'); $query = $this->getCartTotalsGraphqlQuery($maskedQuoteId); $response = $this->sendRequestWithToken($query); self::assertArrayHasKey('prices', $response['cart']); $pricesResponse = $response['cart']['prices']; - self::assertEquals(10.83, $pricesResponse['grand_total']['value']); - self::assertEquals(10.83, $pricesResponse['subtotal_including_tax']['value']); - self::assertEquals(10, $pricesResponse['subtotal_excluding_tax']['value']); - self::assertEquals(10, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); + self::assertEquals(21.5, $pricesResponse['grand_total']['value']); + self::assertEquals(21.5, $pricesResponse['subtotal_including_tax']['value']); + self::assertEquals(20, $pricesResponse['subtotal_excluding_tax']['value']); + self::assertEquals(20, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); $appliedTaxesResponse = $pricesResponse['applied_taxes']; - self::assertEquals('US-CA-*-Rate 1', $appliedTaxesResponse[0]['label']); - self::assertEquals(0.83, $appliedTaxesResponse[0]['amount']['value']); + self::assertEquals('US-TEST-*-Rate-1', $appliedTaxesResponse[0]['label']); + self::assertEquals(1.5, $appliedTaxesResponse[0]['amount']['value']); self::assertEquals('USD', $appliedTaxesResponse[0]['amount']['currency']); } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ public function testGetTotalsWithNoTaxApplied() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_1'); + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_quote'); $query = $this->getCartTotalsGraphqlQuery($maskedQuoteId); $response = $this->sendRequestWithToken($query); @@ -92,19 +104,22 @@ public function testGetTotalsWithNoTaxApplied() * The totals calculation is based on quote address. * But the totals should be calculated even if no address is set * - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_customer_no_address.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ public function testGetCartTotalsWithNoAddressSet() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_1'); + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_quote'); $query = $this->getCartTotalsGraphqlQuery($maskedQuoteId); $response = $this->sendRequestWithToken($query); $pricesResponse = $response['cart']['prices']; - self::assertEquals(10, $pricesResponse['grand_total']['value']); - self::assertEquals(10, $pricesResponse['subtotal_including_tax']['value']); - self::assertEquals(10, $pricesResponse['subtotal_excluding_tax']['value']); - self::assertEquals(10, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); + self::assertEquals(20, $pricesResponse['grand_total']['value']); + self::assertEquals(20, $pricesResponse['subtotal_including_tax']['value']); + self::assertEquals(20, $pricesResponse['subtotal_excluding_tax']['value']); + self::assertEquals(20, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); self::assertEmpty($pricesResponse['applied_taxes']); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php index 19ef071b5040d..9fec6fdfd2697 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php @@ -42,42 +42,52 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_tax_guest.php + * @magentoApiDataFixture Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ public function testGetCartTotalsWithTaxApplied() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_tax'); + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_quote'); $query = $this->getCartTotalsGraphqlQuery($maskedQuoteId); $response = $this->graphQlQuery($query); self::assertArrayHasKey('prices', $response['cart']); $pricesResponse = $response['cart']['prices']; - self::assertEquals(10.83, $pricesResponse['grand_total']['value']); - self::assertEquals(10.83, $pricesResponse['subtotal_including_tax']['value']); - self::assertEquals(10, $pricesResponse['subtotal_excluding_tax']['value']); - self::assertEquals(10, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); + self::assertEquals(21.5, $pricesResponse['grand_total']['value']); + self::assertEquals(21.5, $pricesResponse['subtotal_including_tax']['value']); + self::assertEquals(20, $pricesResponse['subtotal_excluding_tax']['value']); + self::assertEquals(20, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); $appliedTaxesResponse = $pricesResponse['applied_taxes']; - self::assertEquals('US-CA-*-Rate 1', $appliedTaxesResponse[0]['label']); - self::assertEquals(0.83, $appliedTaxesResponse[0]['amount']['value']); + self::assertEquals('US-TEST-*-Rate-1', $appliedTaxesResponse[0]['label']); + self::assertEquals(1.5, $appliedTaxesResponse[0]['amount']['value']); self::assertEquals('USD', $appliedTaxesResponse[0]['amount']['currency']); } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_guest.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ public function testGetTotalsWithNoTaxApplied() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_1'); + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_quote'); $query = $this->getCartTotalsGraphqlQuery($maskedQuoteId); $response = $this->graphQlQuery($query); $pricesResponse = $response['cart']['prices']; - self::assertEquals(10, $pricesResponse['grand_total']['value']); - self::assertEquals(10, $pricesResponse['subtotal_including_tax']['value']); - self::assertEquals(10, $pricesResponse['subtotal_excluding_tax']['value']); - self::assertEquals(10, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); + self::assertEquals(20, $pricesResponse['grand_total']['value']); + self::assertEquals(20, $pricesResponse['subtotal_including_tax']['value']); + self::assertEquals(20, $pricesResponse['subtotal_excluding_tax']['value']); + self::assertEquals(20, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); self::assertEmpty($pricesResponse['applied_taxes']); } @@ -85,19 +95,22 @@ public function testGetTotalsWithNoTaxApplied() * The totals calculation is based on quote address. * But the totals should be calculated even if no address is set * - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @group recent */ public function testGetCartTotalsWithNoAddressSet() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address'); + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_quote'); $query = $this->getCartTotalsGraphqlQuery($maskedQuoteId); $response = $this->graphQlQuery($query); $pricesResponse = $response['cart']['prices']; - self::assertEquals(10, $pricesResponse['grand_total']['value']); - self::assertEquals(10, $pricesResponse['subtotal_including_tax']['value']); - self::assertEquals(10, $pricesResponse['subtotal_excluding_tax']['value']); - self::assertEquals(10, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); + self::assertEquals(20, $pricesResponse['grand_total']['value']); + self::assertEquals(20, $pricesResponse['subtotal_including_tax']['value']); + self::assertEquals(20, $pricesResponse['subtotal_excluding_tax']['value']); + self::assertEquals(20, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); self::assertEmpty($pricesResponse['applied_taxes']); } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_tax.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_tax.php deleted file mode 100644 index 00c2e66736468..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_tax.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Catalog\Model\ProductFactory; -use Magento\Tax\Model\ResourceModel\TaxClass\CollectionFactory as TaxClassCollectionFactory; -use Magento\Tax\Model\ClassModel as TaxClassModel; -use Magento\TestFramework\Helper\Bootstrap; - -$objectManager = Bootstrap::getObjectManager(); -/** @var ProductRepositoryInterface $productRepository */ -$productRepository = $objectManager->create(ProductRepositoryInterface::class); -/** @var ProductFactory $productFactory */ -$productFactory = $objectManager->create(ProductFactory::class); -$product = $productFactory->create(); -$product - ->setTypeId('simple') - ->setId(1) - ->setAttributeSetId(4) - ->setWebsiteIds([1]) - ->setName('Simple Product') - ->setSku('simple') - ->setPrice(10) - ->setMetaTitle('meta title') - ->setMetaKeyword('meta keyword') - ->setMetaDescription('meta description') - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->setStockData(['use_config_manage_stock' => 1, 'qty' => 22, 'is_in_stock' => 1]) - ->setQty(22); - - -/** @var TaxClassCollectionFactory $taxClassCollectionFactory */ -$taxClassCollectionFactory = $objectManager->create(TaxClassCollectionFactory::class); -$taxClassCollection = $taxClassCollectionFactory->create(); - -/** @var TaxClassModel $taxClass */ -$taxClassCollection->addFieldToFilter('class_type', TaxClassModel::TAX_CLASS_TYPE_PRODUCT); -$taxClass = $taxClassCollection->getFirstItem(); - -$product->setCustomAttribute('tax_class_id', $taxClass->getClassId()); -$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_tax_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_tax_rollback.php deleted file mode 100644 index a7d58fdf7f6f6..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_tax_rollback.php +++ /dev/null @@ -1,8 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -require __DIR__ . '/product_simple_rollback.php'; -require __DIR__ . '/../../Tax/_files/tax_classes_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_address_guest.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_address_guest.php deleted file mode 100644 index da496f01ec05d..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_address_guest.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -use Magento\Quote\Api\Data\AddressInterface; -use Magento\Quote\Model\Quote; - -require __DIR__ . '/../../../Magento/Catalog/_files/products.php'; - -$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); -/** @var AddressInterface $quoteAddress */ -$quoteAddress = $objectManager->create(AddressInterface::class); -$quoteAddress->setData( - [ - 'telephone' => 3468676, - 'postcode' => 75477, - 'country_id' => 'US', - 'city' => 'CityM', - 'company' => 'CompanyName', - 'street' => 'Green str, 67', - 'lastname' => 'Smith', - 'firstname' => 'John', - 'region_id' => 1 - ] -); - -/** @var Quote $quote */ -$quote = $objectManager->create(Quote::class); -$quote->setStoreId( - 1 -)->setIsActive( - true -)->setIsMultiShipping( - false -)->setShippingAddress( - $quoteAddress -)->setBillingAddress( - $quoteAddress -)->setCheckoutMethod( - 'customer' -)->setReservedOrderId( - 'test_order_1' -)->addProduct( - $product -); - -$quoteRepository = $objectManager->get( - \Magento\Quote\Api\CartRepositoryInterface::class -); - -$quoteRepository->save($quote); - -/** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */ -$quoteIdMask = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() - ->create(\Magento\Quote\Model\QuoteIdMaskFactory::class) - ->create(); -$quoteIdMask->setQuoteId($quote->getId()); -$quoteIdMask->setDataChanges(true); -$quoteIdMask->save(); diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_address_guest_rollback.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_address_guest_rollback.php deleted file mode 100644 index 3130ca9353e92..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_address_guest_rollback.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -use Magento\Quote\Model\Quote; -use Magento\Quote\Model\QuoteIdMask; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\TestFramework\ObjectManager; - -require __DIR__ . '/../../../Magento/Catalog/_files/products_rollback.php'; - -/** @var $objectManager ObjectManager */ -$objectManager = Bootstrap::getObjectManager(); -$quote = $objectManager->create(Quote::class); -$quote->load('test_order_1', 'reserved_order_id')->delete(); - -/** @var QuoteIdMask $quoteIdMask */ -$quoteIdMask = $objectManager->create(QuoteIdMask::class); -$quoteIdMask->delete($quote->getId()); diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_customer_no_address.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_customer_no_address.php deleted file mode 100644 index ef030f8bcd923..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_customer_no_address.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -use Magento\Customer\Api\CustomerRepositoryInterface; -use Magento\Quote\Model\Quote; - -require __DIR__ . '/../../Customer/_files/customer.php'; -require __DIR__ . '/../../../Magento/Catalog/_files/products.php'; - -$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - -$customerRepository = $objectManager->create(CustomerRepositoryInterface::class); -$customer = $customerRepository->get('customer@example.com'); - -/** @var Quote $quote */ -$quote = $objectManager->create(Quote::class); -$quote->setStoreId( - 1 -)->setIsActive( - true -)->setIsMultiShipping( - false -)->assignCustomer( - $customer -)->setCheckoutMethod( - 'customer' -)->setReservedOrderId( - 'test_order_1' -)->addProduct( - $product -); - -$quoteRepository = $objectManager->get( - \Magento\Quote\Api\CartRepositoryInterface::class -); - -$quoteRepository->save($quote); - -/** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */ -$quoteIdMask = $objectManager - ->get(\Magento\Quote\Model\QuoteIdMaskFactory::class) - ->create(); -$quoteIdMask->setQuoteId($quote->getId()); -$quoteIdMask->setDataChanges(true); -$quoteIdMask->save(); diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_customer_no_address_rollback.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_customer_no_address_rollback.php deleted file mode 100644 index 83c80d736c16b..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_customer_no_address_rollback.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -use Magento\Quote\Model\Quote; -use Magento\Quote\Model\QuoteIdMask; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\TestFramework\ObjectManager; - -require __DIR__ . '/../../Customer/_files/customer_rollback.php'; -require __DIR__ . '/../../../Magento/Catalog/_files/products_rollback.php'; - -/** @var $objectManager ObjectManager */ -$objectManager = Bootstrap::getObjectManager(); -$quote = $objectManager->create(Quote::class); -$quote->load('test_order_1', 'reserved_order_id')->delete(); - -/** @var QuoteIdMask $quoteIdMask */ -$quoteIdMask = $objectManager->create(QuoteIdMask::class); -$quoteIdMask->delete($quote->getId()); diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_customer.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_customer.php deleted file mode 100644 index e9cb45b546a4e..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_customer.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -use Magento\Customer\Api\AddressRepositoryInterface; -use Magento\Customer\Api\CustomerRepositoryInterface; -use Magento\Quote\Model\Quote; -use Magento\Quote\Model\Quote\Address; - -require __DIR__ . '/../../Customer/_files/customer_with_tax_group.php'; -require __DIR__ . '/../../Customer/_files/customer_address.php'; -require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_with_tax.php'; - -$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - -/** @var AddressRepositoryInterface $addressRepository */ -$addressRepository = $objectManager->get(AddressRepositoryInterface::class); -$customerAddress = $addressRepository->getById(1); -$customerAddress->setRegionId(12); // Taxable region -$addressRepository->save($customerAddress); -/** @var CustomerRepositoryInterface $customerRepository */ -$customerRepository = $objectManager->create(CustomerRepositoryInterface::class); -$customer = $customerRepository->get('customer@example.com'); - -/** @var Address $quoteAddress */ -$quoteAddress = $objectManager->create(Address::class); -$quoteAddress->importCustomerAddressData($customerAddress); - -/** @var Quote $quote */ -$quote = $objectManager->create(Quote::class); -$quote->setStoreId( - 1 -)->setIsActive( - true -)->setIsMultiShipping( - false -)->assignCustomer( - $customer -)->setShippingAddress( - $quoteAddress -)->setBillingAddress( - $quoteAddress -)->setCheckoutMethod( - 'customer' -)->setReservedOrderId( - 'test_order_tax' -)->addProduct( - $product -); - -$quote->getShippingAddress()->setRegionId(12); - -$quoteRepository = $objectManager->get( - \Magento\Quote\Api\CartRepositoryInterface::class -); - -$quoteRepository->save($quote); - -/** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */ -$quoteIdMask = $objectManager - ->get(\Magento\Quote\Model\QuoteIdMaskFactory::class) - ->create(); -$quoteIdMask->setQuoteId($quote->getId()); -$quoteIdMask->setDataChanges(true); -$quoteIdMask->save(); diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_customer_rollback.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_customer_rollback.php deleted file mode 100644 index 1e1eb326d7c8a..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_customer_rollback.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -use Magento\Quote\Model\Quote; -use Magento\Quote\Model\QuoteIdMask; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\TestFramework\ObjectManager; - -require __DIR__ . '/../../Customer/_files/customer_with_tax_group_rollback.php'; -require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_with_tax_rollback.php'; - -/** @var $objectManager ObjectManager */ -$objectManager = Bootstrap::getObjectManager(); -$quote = $objectManager->create(Quote::class); -$quote->load('test_order_tax', 'reserved_order_id')->delete(); - -/** @var QuoteIdMask $quoteIdMask */ -$quoteIdMask = $objectManager->create(QuoteIdMask::class); -$quoteIdMask->delete($quote->getId()); diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_guest.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_guest.php deleted file mode 100644 index 78d5b0739d763..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_guest.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -use Magento\Quote\Api\Data\AddressInterface; -use Magento\Quote\Model\Quote; - -require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_with_tax.php'; - -$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); -/** @var AddressInterface $quoteAddress */ -$quoteAddress = $objectManager->create(AddressInterface::class); -$quoteAddress->setData( - [ - 'telephone' => 3468676, - 'postcode' => 75477, - 'country_id' => 'US', - 'city' => 'CityM', - 'company' => 'CompanyName', - 'street' => 'Green str, 67', - 'lastname' => 'Smith', - 'firstname' => 'John', - 'region_id' => 12 - ] -); - -/** @var Quote $quote */ -$quote = $objectManager->create(Quote::class); -$quote->setStoreId( - 1 -)->setIsActive( - true -)->setIsMultiShipping( - false -)->setShippingAddress( - $quoteAddress -)->setBillingAddress( - $quoteAddress -)->setCheckoutMethod( - 'guest' -)->setReservedOrderId( - 'test_order_tax' -)->addProduct( - $product -); - -$quote->getShippingAddress()->setRegionId(12); - -$quoteRepository = $objectManager->get( - \Magento\Quote\Api\CartRepositoryInterface::class -); - -$quoteRepository->save($quote); - -/** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */ -$quoteIdMask = $objectManager - ->get(\Magento\Quote\Model\QuoteIdMaskFactory::class) - ->create(); -$quoteIdMask->setQuoteId($quote->getId()); -$quoteIdMask->setDataChanges(true); -$quoteIdMask->save(); diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_guest_rollback.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_guest_rollback.php deleted file mode 100644 index 6fcbdf7276de2..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_tax_guest_rollback.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -use Magento\Quote\Model\Quote; -use Magento\Quote\Model\QuoteIdMask; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\TestFramework\ObjectManager; - -require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_with_tax_rollback.php'; - -/** @var $objectManager ObjectManager */ -$objectManager = Bootstrap::getObjectManager(); -$quote = $objectManager->create(Quote::class); -$quote->load('test_order_tax', 'reserved_order_id')->delete(); - -/** @var QuoteIdMask $quoteIdMask */ -$quoteIdMask = $objectManager->create(QuoteIdMask::class); -$quoteIdMask->delete($quote->getId()); diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_with_tax_group.php b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_with_tax_group.php deleted file mode 100644 index 4792df5cdb2f7..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_with_tax_group.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -require __DIR__ . '/customer.php'; - -$customer->setGroupId(3); // 3 is a predefined retailer group -$customer->save(); diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_with_tax_group_rollback.php b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_with_tax_group_rollback.php deleted file mode 100644 index 48a09a41c7e07..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_with_tax_group_rollback.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -require __DIR__ . '/customer_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php new file mode 100644 index 0000000000000..9968704517ecd --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Tax\Model\ClassModel as TaxClassModel; +use Magento\Tax\Model\ResourceModel\TaxClass\CollectionFactory as TaxClassCollectionFactory; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$product = $productRepository->get('simple_product'); + +/** @var TaxClassCollectionFactory $taxClassCollectionFactory */ +$taxClassCollectionFactory = $objectManager->get(TaxClassCollectionFactory::class); +$taxClassCollection = $taxClassCollectionFactory->create(); + +/** @var TaxClassModel $taxClass */ +$taxClassCollection->addFieldToFilter('class_type', TaxClassModel::TAX_CLASS_TYPE_PRODUCT); +$taxClass = $taxClassCollection->getFirstItem(); + +$product->setCustomAttribute('tax_class_id', $taxClass->getClassId()); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php b/dev/tests/integration/testsuite/Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php new file mode 100644 index 0000000000000..aca55bd8414f6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Tax\Api\Data\TaxRateInterface; +use Magento\Tax\Api\Data\TaxRuleInterface; +use Magento\Tax\Api\TaxRateRepositoryInterface; +use Magento\Tax\Api\TaxRuleRepositoryInterface; +use Magento\Tax\Model\Calculation\Rate; +use Magento\Tax\Model\Calculation\RateFactory; +use Magento\Tax\Model\Calculation\RateRepository; +use Magento\Tax\Model\Calculation\Rule; +use Magento\Tax\Model\Calculation\RuleFactory; +use Magento\Tax\Model\TaxRuleRepository; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Framework\Api\DataObjectHelper; + +$objectManager = Bootstrap::getObjectManager(); +/** @var DataObjectHelper $dataObjectHelper */ +$dataObjectHelper = Bootstrap::getObjectManager()->get(DataObjectHelper::class); +/** @var RateFactory $rateFactory */ +$rateFactory = $objectManager->get(RateFactory::class); +/** @var RuleFactory $ruleFactory */ +$ruleFactory = $objectManager->get(RuleFactory::class); +/** @var RateRepository $rateRepository */ +$rateRepository = $objectManager->get(TaxRateRepositoryInterface::class); +/** @var TaxRuleRepository $ruleRepository */ +$ruleRepository = $objectManager->get(TaxRuleRepositoryInterface::class); +/** @var Rate $rate */ +$rate = $rateFactory->create(); +$rateData = [ + Rate::KEY_COUNTRY_ID => 'US', + Rate::KEY_REGION_ID => '1', + Rate::KEY_POSTCODE => '*', + Rate::KEY_CODE => 'US-TEST-*-Rate-1', + Rate::KEY_PERCENTAGE_RATE => '7.5', +]; +$dataObjectHelper->populateWithArray($rate, $rateData, TaxRateInterface::class); +$rateRepository->save($rate); + +$rule = $ruleFactory->create(); +$ruleData = [ + Rule::KEY_CODE=> 'GraphQl Test Rule', + Rule::KEY_PRIORITY => '0', + Rule::KEY_POSITION => '0', + Rule::KEY_CUSTOMER_TAX_CLASS_IDS => [3], + Rule::KEY_PRODUCT_TAX_CLASS_IDS => [2], + Rule::KEY_TAX_RATE_IDS => [$rate->getId()], +]; +$dataObjectHelper->populateWithArray($rule, $ruleData, TaxRuleInterface::class); +$ruleRepository->save($rule); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Tax/_files/tax_rule_for_region_1_rollback.php b/dev/tests/integration/testsuite/Magento/GraphQl/Tax/_files/tax_rule_for_region_1_rollback.php new file mode 100644 index 0000000000000..aba1960624ed4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Tax/_files/tax_rule_for_region_1_rollback.php @@ -0,0 +1,38 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Tax\Api\TaxRateRepositoryInterface; +use Magento\Tax\Api\TaxRuleRepositoryInterface; +use Magento\Tax\Model\Calculation\Rate; +use Magento\Tax\Model\Calculation\RateFactory; +use Magento\Tax\Model\Calculation\RateRepository; +use Magento\Tax\Model\Calculation\Rule; +use Magento\Tax\Model\Calculation\RuleFactory; +use Magento\Tax\Model\TaxRuleRepository; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Tax\Model\ResourceModel\Calculation\Rate as RateResource; +use Magento\Tax\Model\ResourceModel\Calculation\Rule as RuleResource; + +$objectManager = Bootstrap::getObjectManager(); +/** @var RateFactory $rateFactory */ +$rateFactory = $objectManager->get(RateFactory::class); +/** @var RuleFactory $ruleFactory */ +$ruleFactory = $objectManager->get(RuleFactory::class); +/** @var RateRepository $rateRepository */ +$rateRepository = $objectManager->get(TaxRateRepositoryInterface::class); +/** @var TaxRuleRepository $ruleRepository */ +$ruleRepository = $objectManager->get(TaxRuleRepositoryInterface::class); +/** @var RateResource $rateResource */ +$rateResource = $objectManager->get(RateResource::class); +/** @var RuleResource $ruleResource */ +$ruleResource = $objectManager->get(RuleResource::class); + +$rate = $rateFactory->create(); +$rateResource->load($rate, 'US-TEST-*-Rate-1', Rate::KEY_CODE); +$rule = $ruleFactory->create(); +$ruleResource->load($rule, 'GraphQl Test Rule', Rule::KEY_CODE); +$ruleRepository->delete($rule); +$rateRepository->delete($rate); From a2b2aa0e5db615843ba00bf332aca0b38fe3236b Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 11 Apr 2019 15:47:21 +0300 Subject: [PATCH 461/603] magento/magento2#20832: MFTF test fix. --- .../Test/Mftf/ActionGroup/StorefrontCustomerActionGroup.xml | 4 ++-- .../Test/Mftf/Section/StorefrontPanelHeaderSection.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerActionGroup.xml index fc5c1b881752e..c3b92b1af7f82 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerActionGroup.xml @@ -9,8 +9,8 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="CustomerLogoutStorefrontByMenuItemsActionGroup"> - <conditionalClick selector="{{StorefrontPanelHeaderSection.customerWelcome}}" - dependentSelector="{{StorefrontPanelHeaderSection.customerWelcomeMenu}}" + <conditionalClick selector="{{StorefrontPanelHeaderSection.customerWelcomeMenu}}" + dependentSelector="{{StorefrontPanelHeaderSection.customerLogoutLink}}" visible="false" stepKey="clickHeaderCustomerMenuButton" /> <click selector="{{StorefrontPanelHeaderSection.customerLogoutLink}}" stepKey="clickSignOutButton" /> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml index 0505aa908f2a0..3610532c5356b 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml @@ -16,8 +16,8 @@ <element name="createAnAccountLink" type="select" selector="//div[@class='panel wrapper']//li/a[contains(.,'Create an Account')]" timeout="30"/> <element name="notYouLink" type="button" selector=".greet.welcome span a"/> <element name="customerWelcome" type="text" selector=".panel.header .greet.welcome"/> - <element name="customerWelcomeMenu" type="text" selector=".panel.header .greet.welcome .customer-menu"/> + <element name="customerWelcomeMenu" type="text" selector=".panel.header .customer-welcome .customer-name"/> <element name="customerLoginLink" type="button" selector=".panel.header .header.links .authorization-link a" timeout="30"/> - <element name="customerLogoutLink" type="text" selector=".panel.header .greet.welcome .customer-menu .authorization-link a" timeout="30"/> + <element name="customerLogoutLink" type="text" selector=".panel.header .customer-welcome .customer-menu .authorization-link a" timeout="30"/> </section> </sections> From 91f116d99c0aeec8fb9af15d594da4276b44abd6 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Wed, 10 Apr 2019 14:58:00 +0300 Subject: [PATCH 462/603] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Fixed static/unit test falls; --- app/code/Magento/Ups/Model/Carrier.php | 289 +++++++++++++++---------- 1 file changed, 169 insertions(+), 120 deletions(-) diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index 14b71e5f75db3..09d6ba154a546 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -455,7 +455,7 @@ protected function _getCgiQuotes() { $rowRequest = $this->_rawRequest; if (self::USA_COUNTRY_ID == $rowRequest->getDestCountry()) { - $destPostal = substr($rowRequest->getDestPostal(), 0, 5); + $destPostal = substr((string)$rowRequest->getDestPostal(), 0, 5); } else { $destPostal = $rowRequest->getDestPostal(); } @@ -613,7 +613,7 @@ protected function _getXmlQuotes() $rowRequest = $this->_rawRequest; if (self::USA_COUNTRY_ID == $rowRequest->getDestCountry()) { - $destPostal = substr($rowRequest->getDestPostal(), 0, 5); + $destPostal = substr((string)$rowRequest->getDestPostal(), 0, 5); } else { $destPostal = $rowRequest->getDestPostal(); } @@ -833,76 +833,15 @@ protected function _parseXmlResponse($xmlResponse) $allowedCurrencies = $this->_currencyFactory->create()->getConfigAllowCurrencies(); foreach ($arr as $shipElement) { - $code = (string)$shipElement->Service->Code; - if (in_array($code, $allowedMethods)) { - //The location of tax information is in a different place - // depending on whether we are using negotiated rates or not - if ($negotiatedActive) { - $includeTaxesArr = $xml->getXpath( - "//RatingServiceSelectionResponse/RatedShipment/NegotiatedRates" - . "/NetSummaryCharges/TotalChargesWithTaxes" - ); - $includeTaxesActive = $this->getConfigFlag('include_taxes') && !empty($includeTaxesArr); - if ($includeTaxesActive) { - $cost = $shipElement->NegotiatedRates - ->NetSummaryCharges - ->TotalChargesWithTaxes - ->MonetaryValue; - - $responseCurrencyCode = $this->mapCurrencyCode( - (string)$shipElement->NegotiatedRates - ->NetSummaryCharges - ->TotalChargesWithTaxes - ->CurrencyCode - ); - } else { - $cost = $shipElement->NegotiatedRates->NetSummaryCharges->GrandTotal->MonetaryValue; - $responseCurrencyCode = $this->mapCurrencyCode( - (string)$shipElement->NegotiatedRates->NetSummaryCharges->GrandTotal->CurrencyCode - ); - } - } else { - $includeTaxesArr = $xml->getXpath( - "//RatingServiceSelectionResponse/RatedShipment/TotalChargesWithTaxes" - ); - $includeTaxesActive = $this->getConfigFlag('include_taxes') && !empty($includeTaxesArr); - if ($includeTaxesActive) { - $cost = $shipElement->TotalChargesWithTaxes->MonetaryValue; - $responseCurrencyCode = $this->mapCurrencyCode( - (string)$shipElement->TotalChargesWithTaxes->CurrencyCode - ); - } else { - $cost = $shipElement->TotalCharges->MonetaryValue; - $responseCurrencyCode = $this->mapCurrencyCode( - (string)$shipElement->TotalCharges->CurrencyCode - ); - } - } - - //convert price with Origin country currency code to base currency code - $successConversion = true; - if ($responseCurrencyCode) { - if (in_array($responseCurrencyCode, $allowedCurrencies)) { - $cost = (double)$cost * $this->_getBaseCurrencyRate($responseCurrencyCode); - } else { - $errorTitle = __( - 'We can\'t convert a rate from "%1-%2".', - $responseCurrencyCode, - $this->_request->getPackageCurrency()->getCode() - ); - $error = $this->_rateErrorFactory->create(); - $error->setCarrier('ups'); - $error->setCarrierTitle($this->getConfigData('title')); - $error->setErrorMessage($errorTitle); - $successConversion = false; - } - } - - if ($successConversion) { - $costArr[$code] = $cost; - $priceArr[$code] = $this->getMethodPrice((float)$cost, $code); - } - } + $this->processShippingRateForItem( + $shipElement, + $allowedMethods, + $allowedCurrencies, + $costArr, + $priceArr, + $negotiatedActive, + $xml + ); } } else { $arr = $xml->getXpath("//RatingServiceSelectionResponse/Response/Error/ErrorDescription/text()"); @@ -945,6 +884,99 @@ protected function _parseXmlResponse($xmlResponse) return $result; } + /** + * Processing rate for ship element + * + * @param \Magento\Framework\Simplexml\Element $shipElement + * @param array $allowedMethods + * @param array $allowedCurrencies + * @param array $costArr + * @param array $priceArr + * @param bool $negotiatedActive + * @param \Magento\Framework\Simplexml\Config $xml + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + private function processShippingRateForItem( + \Magento\Framework\Simplexml\Element $shipElement, + array $allowedMethods, + array $allowedCurrencies, + array &$costArr, + array &$priceArr, + bool $negotiatedActive, + \Magento\Framework\Simplexml\Config $xml + ): void { + $code = (string)$shipElement->Service->Code; + if (in_array($code, $allowedMethods)) { + //The location of tax information is in a different place + // depending on whether we are using negotiated rates or not + if ($negotiatedActive) { + $includeTaxesArr = $xml->getXpath( + "//RatingServiceSelectionResponse/RatedShipment/NegotiatedRates" + . "/NetSummaryCharges/TotalChargesWithTaxes" + ); + $includeTaxesActive = $this->getConfigFlag('include_taxes') && !empty($includeTaxesArr); + if ($includeTaxesActive) { + $cost = $shipElement->NegotiatedRates + ->NetSummaryCharges + ->TotalChargesWithTaxes + ->MonetaryValue; + + $responseCurrencyCode = $this->mapCurrencyCode( + (string)$shipElement->NegotiatedRates + ->NetSummaryCharges + ->TotalChargesWithTaxes + ->CurrencyCode + ); + } else { + $cost = $shipElement->NegotiatedRates->NetSummaryCharges->GrandTotal->MonetaryValue; + $responseCurrencyCode = $this->mapCurrencyCode( + (string)$shipElement->NegotiatedRates->NetSummaryCharges->GrandTotal->CurrencyCode + ); + } + } else { + $includeTaxesArr = $xml->getXpath( + "//RatingServiceSelectionResponse/RatedShipment/TotalChargesWithTaxes" + ); + $includeTaxesActive = $this->getConfigFlag('include_taxes') && !empty($includeTaxesArr); + if ($includeTaxesActive) { + $cost = $shipElement->TotalChargesWithTaxes->MonetaryValue; + $responseCurrencyCode = $this->mapCurrencyCode( + (string)$shipElement->TotalChargesWithTaxes->CurrencyCode + ); + } else { + $cost = $shipElement->TotalCharges->MonetaryValue; + $responseCurrencyCode = $this->mapCurrencyCode( + (string)$shipElement->TotalCharges->CurrencyCode + ); + } + } + + //convert price with Origin country currency code to base currency code + $successConversion = true; + if ($responseCurrencyCode) { + if (in_array($responseCurrencyCode, $allowedCurrencies)) { + $cost = (double)$cost * $this->_getBaseCurrencyRate($responseCurrencyCode); + } else { + $errorTitle = __( + 'We can\'t convert a rate from "%1-%2".', + $responseCurrencyCode, + $this->_request->getPackageCurrency()->getCode() + ); + $error = $this->_rateErrorFactory->create(); + $error->setCarrier('ups'); + $error->setCarrierTitle($this->getConfigData('title')); + $error->setErrorMessage($errorTitle); + $successConversion = false; + } + } + + if ($successConversion) { + $costArr[$code] = $cost; + $priceArr[$code] = $this->getMethodPrice((float)$cost, $code); + } + } + } + /** * Get tracking * @@ -1101,54 +1133,7 @@ protected function _parseXmlTrackingResponse($trackingValue, $xmlResponse) if ($activityTags) { $index = 1; foreach ($activityTags as $activityTag) { - $addressArr = []; - if (isset($activityTag->ActivityLocation->Address->City)) { - $addressArr[] = (string)$activityTag->ActivityLocation->Address->City; - } - if (isset($activityTag->ActivityLocation->Address->StateProvinceCode)) { - $addressArr[] = (string)$activityTag->ActivityLocation->Address->StateProvinceCode; - } - if (isset($activityTag->ActivityLocation->Address->CountryCode)) { - $addressArr[] = (string)$activityTag->ActivityLocation->Address->CountryCode; - } - $dateArr = []; - $date = (string)$activityTag->Date; - //YYYYMMDD - $dateArr[] = substr($date, 0, 4); - $dateArr[] = substr($date, 4, 2); - $dateArr[] = substr($date, -2, 2); - - $timeArr = []; - $time = (string)$activityTag->Time; - //HHMMSS - $timeArr[] = substr($time, 0, 2); - $timeArr[] = substr($time, 2, 2); - $timeArr[] = substr($time, -2, 2); - - if ($index === 1) { - $resultArr['status'] = (string)$activityTag->Status->StatusType->Description; - $resultArr['deliverydate'] = implode('-', $dateArr); - //YYYY-MM-DD - $resultArr['deliverytime'] = implode(':', $timeArr); - //HH:MM:SS - $resultArr['deliverylocation'] = (string)$activityTag->ActivityLocation->Description; - $resultArr['signedby'] = (string)$activityTag->ActivityLocation->SignedForByName; - if ($addressArr) { - $resultArr['deliveryto'] = implode(', ', $addressArr); - } - } else { - $tempArr = []; - $tempArr['activity'] = (string)$activityTag->Status->StatusType->Description; - $tempArr['deliverydate'] = implode('-', $dateArr); - //YYYY-MM-DD - $tempArr['deliverytime'] = implode(':', $timeArr); - //HH:MM:SS - if ($addressArr) { - $tempArr['deliverylocation'] = implode(', ', $addressArr); - } - $packageProgress[] = $tempArr; - } - $index++; + $this->processActivityTagInfo($activityTag, $index, $resultArr, $packageProgress); } $resultArr['progressdetail'] = $packageProgress; } @@ -1181,6 +1166,70 @@ protected function _parseXmlTrackingResponse($trackingValue, $xmlResponse) return $this->_result; } + /** + * Process tracking info from activity tag + * + * @param \Magento\Framework\Simplexml\Element $activityTag + * @param int $index + * @param array $resultArr + * @param array $packageProgress + */ + private function processActivityTagInfo( + \Magento\Framework\Simplexml\Element $activityTag, + int &$index, + array &$resultArr, + array &$packageProgress + ) { + $addressArr = []; + if (isset($activityTag->ActivityLocation->Address->City)) { + $addressArr[] = (string)$activityTag->ActivityLocation->Address->City; + } + if (isset($activityTag->ActivityLocation->Address->StateProvinceCode)) { + $addressArr[] = (string)$activityTag->ActivityLocation->Address->StateProvinceCode; + } + if (isset($activityTag->ActivityLocation->Address->CountryCode)) { + $addressArr[] = (string)$activityTag->ActivityLocation->Address->CountryCode; + } + $dateArr = []; + $date = (string)$activityTag->Date; + //YYYYMMDD + $dateArr[] = substr($date, 0, 4); + $dateArr[] = substr($date, 4, 2); + $dateArr[] = substr($date, -2, 2); + + $timeArr = []; + $time = (string)$activityTag->Time; + //HHMMSS + $timeArr[] = substr($time, 0, 2); + $timeArr[] = substr($time, 2, 2); + $timeArr[] = substr($time, -2, 2); + + if ($index === 1) { + $resultArr['status'] = (string)$activityTag->Status->StatusType->Description; + $resultArr['deliverydate'] = implode('-', $dateArr); + //YYYY-MM-DD + $resultArr['deliverytime'] = implode(':', $timeArr); + //HH:MM:SS + $resultArr['deliverylocation'] = (string)$activityTag->ActivityLocation->Description; + $resultArr['signedby'] = (string)$activityTag->ActivityLocation->SignedForByName; + if ($addressArr) { + $resultArr['deliveryto'] = implode(', ', $addressArr); + } + } else { + $tempArr = []; + $tempArr['activity'] = (string)$activityTag->Status->StatusType->Description; + $tempArr['deliverydate'] = implode('-', $dateArr); + //YYYY-MM-DD + $tempArr['deliverytime'] = implode(':', $timeArr); + //HH:MM:SS + if ($addressArr) { + $tempArr['deliverylocation'] = implode(', ', $addressArr); + } + $packageProgress[] = $tempArr; + } + $index++; + } + /** * Get tracking response * From 6cc22442ec2569545e708149ef04880614d6cc80 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Thu, 11 Apr 2019 17:36:54 +0300 Subject: [PATCH 463/603] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Fixed unit tests; --- app/code/Magento/Ups/Model/Carrier.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index 09d6ba154a546..d3a0bb86b0496 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -473,7 +473,7 @@ protected function _getCgiQuotes() '47_rate_chart' => $rowRequest->getPickup(), '48_container' => $rowRequest->getContainer(), '49_residential' => $rowRequest->getDestType(), - 'weight_std' => strtolower($rowRequest->getUnitMeasure()), + 'weight_std' => strtolower((string)$rowRequest->getUnitMeasure()), ]; $params['47_rate_chart'] = $params['47_rate_chart']['label']; @@ -537,7 +537,7 @@ protected function _parseCgiResponse($response) $priceArr = []; if (strlen(trim($response)) > 0) { $rRows = explode("\n", $response); - $allowedMethods = explode(",", $this->getConfigData('allowed_methods')); + $allowedMethods = explode(",", (string)$this->getConfigData('allowed_methods')); foreach ($rRows as $rRow) { $row = explode('%', $rRow); switch (substr($row[0], -1)) { From 6d873304742ee5114ec661d6b799bd2f0a4f3cff Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Thu, 11 Apr 2019 17:39:28 +0300 Subject: [PATCH 464/603] Fix static tests. --- lib/internal/Magento/Framework/Code/Generator.php | 3 +++ .../Magento/Framework/Code/Test/Unit/GeneratorTest.php | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Code/Generator.php b/lib/internal/Magento/Framework/Code/Generator.php index ba4213f398008..b46c8c681bb52 100644 --- a/lib/internal/Magento/Framework/Code/Generator.php +++ b/lib/internal/Magento/Framework/Code/Generator.php @@ -14,6 +14,9 @@ use Magento\Framework\Filesystem\Driver\File; use Psr\Log\LoggerInterface; +/** + * Class code generator. + */ class Generator { const GENERATION_SUCCESS = 'success'; diff --git a/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php b/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php index 98700ae8917f1..2753561683385 100644 --- a/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php +++ b/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php @@ -23,6 +23,11 @@ use Magento\GeneratedClass\Factory as GeneratedClassFactory; use RuntimeException; +/** + * Tests for code generator. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class GeneratorTest extends TestCase { /** @@ -143,7 +148,7 @@ public function testGenerateClass($className, $entityType): void $this->assertSame( Generator::GENERATION_SUCCESS, - $this->model->generateClass(GeneratedClassFactory::class) + $this->model->generateClass($fullClassName) ); } From 316133a0c2373bab06dfe81d926baec720a3dd92 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 11 Apr 2019 17:44:22 +0300 Subject: [PATCH 465/603] magento/magento2#20968: Unit test fix. --- .../Store/Test/Unit/Model/StoreTest.php | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Store/Test/Unit/Model/StoreTest.php b/app/code/Magento/Store/Test/Unit/Model/StoreTest.php index f4a5010e51b88..dddc6828eb961 100644 --- a/app/code/Magento/Store/Test/Unit/Model/StoreTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/StoreTest.php @@ -160,7 +160,7 @@ public function testGetWebsite() /** @var \Magento\Store\Model\Store $model */ $model = $this->objectManagerHelper->getObject( \Magento\Store\Model\Store::class, - ['websiteRepository' => $websiteRepository,] + ['websiteRepository' => $websiteRepository] ); $model->setWebsiteId($websiteId); @@ -181,7 +181,7 @@ public function testGetWebsiteIfWebsiteIsNotExist() /** @var \Magento\Store\Model\Store $model */ $model = $this->objectManagerHelper->getObject( \Magento\Store\Model\Store::class, - ['websiteRepository' => $websiteRepository,] + ['websiteRepository' => $websiteRepository] ); $model->setWebsiteId(null); @@ -207,7 +207,7 @@ public function testGetGroup() /** @var \Magento\Store\Model\Store $model */ $model = $this->objectManagerHelper->getObject( \Magento\Store\Model\Store::class, - ['groupRepository' => $groupRepository,] + ['groupRepository' => $groupRepository] ); $model->setGroupId($groupId); @@ -228,7 +228,7 @@ public function testGetGroupIfGroupIsNotExist() /** @var \Magento\Store\Model\Store $model */ $model = $this->objectManagerHelper->getObject( \Magento\Store\Model\Store::class, - ['groupRepository' => $groupRepository,] + ['groupRepository' => $groupRepository] ); $model->setGroupId(null); @@ -377,30 +377,31 @@ public function testGetBaseUrlEntryPoint() $configMock = $this->getMockForAbstractClass(\Magento\Framework\App\Config\ReinitableConfigInterface::class); $configMock->expects($this->atLeastOnce()) ->method('getValue') - ->will($this->returnCallback( - function ($path, $scope, $scopeCode) use ($expectedPath) { - return $expectedPath == $path ? 'http://domain.com/' . $path . '/' : null; - } - )); + ->willReturnCallback(function ($path, $scope, $scopeCode) use ($expectedPath) { + return $expectedPath == $path ? 'http://domain.com/' . $path . '/' : null; + }); + $this->requestMock->expects($this->once()) + ->method('getServer') + ->with('SCRIPT_FILENAME') + ->willReturn('test_script.php'); + /** @var \Magento\Store\Model\Store $model */ $model = $this->objectManagerHelper->getObject( \Magento\Store\Model\Store::class, [ 'config' => $configMock, 'isCustomEntryPoint' => false, + 'request' => $this->requestMock ] ); $model->setCode('scopeCode'); $this->setUrlModifier($model); - $server = $_SERVER; - $_SERVER['SCRIPT_FILENAME'] = 'test_script.php'; $this->assertEquals( $expectedBaseUrl, $model->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_LINK, false) ); - $_SERVER = $server; } /** @@ -592,7 +593,7 @@ public function testGetAllowedCurrencies() /** @var \Magento\Store\Model\Store $model */ $model = $this->objectManagerHelper->getObject( \Magento\Store\Model\Store::class, - ['config' => $configMock, 'currencyInstalled' => $currencyPath,] + ['config' => $configMock, 'currencyInstalled' => $currencyPath] ); $this->assertEquals($expectedResult, $model->getAllowedCurrencies()); @@ -666,8 +667,7 @@ public function isCurrentlySecureDataProvider() 'unsecure request, no secure base url registered' => [false, 443, false, true, null], 'unsecure request, not using registered port' => [false, 80], 'unsecure request, using registered port, not using secure in frontend' => [false, 443, false, false], - 'unsecure request, no secure base url registered, not using secure in frontend' => - [false, 443, false, false, null], + 'unsecure request, no secure base url registered, not using secure in frontend' => [false, 443, false, false, null], 'unsecure request, not using registered port, not using secure in frontend' => [false, 80, false, false], ]; } From 977a18a86f0fdcaae1926f0730c4e31ee022c743 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 11 Apr 2019 17:44:50 +0300 Subject: [PATCH 466/603] magento/magento2#20968: Integration tests fix. --- .../Plugin/RequestPreprocessorTest.php | 2 +- .../Magento/Store/Model/StoreTest.php | 21 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Store/App/FrontController/Plugin/RequestPreprocessorTest.php b/dev/tests/integration/testsuite/Magento/Store/App/FrontController/Plugin/RequestPreprocessorTest.php index ebf302c16bd69..0e158821f1802 100644 --- a/dev/tests/integration/testsuite/Magento/Store/App/FrontController/Plugin/RequestPreprocessorTest.php +++ b/dev/tests/integration/testsuite/Magento/Store/App/FrontController/Plugin/RequestPreprocessorTest.php @@ -56,7 +56,7 @@ public function testHttpsPassSecureLoginPost() $this->prepareRequest(true); $this->dispatch('customer/account/loginPost/'); $redirectUrl = str_replace('http://', 'https://', $this->baseUrl) . - 'index.php/customer/account/'; + 'customer/account/'; $this->assertResponseRedirect($this->getResponse(), $redirectUrl); $this->assertTrue($this->_objectManager->get(Session::class)->isLoggedIn()); $this->setFrontendCompletelySecureRollback(); diff --git a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php index bb6d1687052e3..32862ed99c475 100644 --- a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php +++ b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php @@ -8,7 +8,6 @@ use Magento\Catalog\Model\ProductRepository; use Magento\Framework\App\Bootstrap; -use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\UrlInterface; use Magento\Store\Api\StoreRepositoryInterface; @@ -201,7 +200,7 @@ public function testGetBaseUrlInPub() */ public function testGetBaseUrlForCustomEntryPoint($type, $useCustomEntryPoint, $useStoreCode, $expected) { - /* config operations require store to be loaded */ + /* config operations require store to be loaded */ $this->model->load('default'); \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->get(\Magento\Framework\App\Config\MutableScopeConfigInterface::class) @@ -213,6 +212,10 @@ public function testGetBaseUrlForCustomEntryPoint($type, $useCustomEntryPoint, $ // emulate custom entry point $_SERVER['SCRIPT_FILENAME'] = 'custom_entry.php'; + $request = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->get(\Magento\Framework\App\RequestInterface::class); + $request->setServer(new Parameters($_SERVER)); + if ($useCustomEntryPoint) { $property = new \ReflectionProperty($this->model, '_isCustomEntryPoint'); $property->setAccessible(true); @@ -298,11 +301,11 @@ public function testGetCurrentUrl() $url = $product->getUrlInStore(); $this->assertEquals( - $secondStore->getBaseUrl().'catalog/product/view/id/1/s/simple-product/', + $secondStore->getBaseUrl() . 'catalog/product/view/id/1/s/simple-product/', $url ); $this->assertEquals( - $secondStore->getBaseUrl().'?___from_store=default', + $secondStore->getBaseUrl() . '?___from_store=default', $secondStore->getCurrentUrl() ); $this->assertEquals( @@ -332,25 +335,25 @@ public function testGetCurrentUrlWithUseStoreInUrlFalse() $product->setStoreId($secondStore->getId()); $url = $product->getUrlInStore(); - /** @var \Magento\Catalog\Model\CategoryRepository $categoryRepository */ + /** @var \Magento\Catalog\Model\CategoryRepository $categoryRepository */ $categoryRepository = $objectManager->get(\Magento\Catalog\Model\CategoryRepository::class); $category = $categoryRepository->get(333, $secondStore->getStoreId()); $this->assertEquals( - $secondStore->getBaseUrl().'catalog/category/view/s/category-1/id/333/', + $secondStore->getBaseUrl() . 'catalog/category/view/s/category-1/id/333/', $category->getUrl() ); $this->assertEquals( - $secondStore->getBaseUrl(). + $secondStore->getBaseUrl() . 'catalog/product/view/id/333/s/simple-product-three/?___store=fixture_second_store', $url ); $this->assertEquals( - $secondStore->getBaseUrl().'?___store=fixture_second_store&___from_store=default', + $secondStore->getBaseUrl() . '?___store=fixture_second_store&___from_store=default', $secondStore->getCurrentUrl() ); $this->assertEquals( - $secondStore->getBaseUrl().'?___store=fixture_second_store', + $secondStore->getBaseUrl() . '?___store=fixture_second_store', $secondStore->getCurrentUrl(false) ); } From c5fc16047c84f3c458c31011080fcca85182e669 Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Thu, 11 Apr 2019 13:13:49 -0500 Subject: [PATCH 467/603] MC-15824: Create new GraphQL script for our benchmark - part 3 --- setup/performance-toolkit/benchmark.jmx | 2648 +++++++++++++++++++---- 1 file changed, 2272 insertions(+), 376 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index cfabe613a0ea1..760cba726def6 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -374,6 +374,16 @@ <stringProp name="Argument.value">${__P(graphqlAddSimpleProductToCartPercentage,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> + <elementProp name="graphqlCheckoutByGuestPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlCheckoutByGuestPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlCheckoutByGuestPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="graphqlCreateEmptyCartPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlCreateEmptyCartPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlCreateEmptyCartPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> <elementProp name="graphqlGetCategoryListByCategoryIdPercentage" elementType="Argument"> <stringProp name="Argument.name">graphqlGetCategoryListByCategoryIdPercentage</stringProp> <stringProp name="Argument.value">${__P(graphqlGetCategoryListByCategoryIdPercentage,0)}</stringProp> @@ -399,6 +409,11 @@ <stringProp name="Argument.value">${__P(graphqlGetConfigurableProductDetailsByProductUrlKeyPercentage,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> + <elementProp name="graphqlGetEmptyCartPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlGetEmptyCartPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlGetEmptyCartPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> <elementProp name="graphqlGetListOfProductsByCategoryIdPercentage" elementType="Argument"> <stringProp name="Argument.name">graphqlGetListOfProductsByCategoryIdPercentage</stringProp> <stringProp name="Argument.value">${__P(graphqlGetListOfProductsByCategoryIdPercentage,0)}</stringProp> @@ -409,11 +424,6 @@ <stringProp name="Argument.value">${__P(graphqlGetNavigationMenuByCategoryIdPercentage,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="graphqlGetProductDetailByProductNamePercentage" elementType="Argument"> - <stringProp name="Argument.name">graphqlGetProductDetailByProductNamePercentage</stringProp> - <stringProp name="Argument.value">${__P(graphqlGetProductDetailByProductNamePercentage,0)}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> <elementProp name="graphqlGetProductSearchByTextAndCategoryIdPercentage" elementType="Argument"> <stringProp name="Argument.name">graphqlGetProductSearchByTextAndCategoryIdPercentage</stringProp> <stringProp name="Argument.value">${__P(graphqlGetProductSearchByTextAndCategoryIdPercentage,0)}</stringProp> @@ -429,6 +439,36 @@ <stringProp name="Argument.value">${__P(graphqlGetSimpleProductDetailsByProductUrlKeyPercentage,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> + <elementProp name="graphqlRemoveConfigurableProductFromCartPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlRemoveConfigurableProductFromCartPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlRemoveConfigurableProductFromCartPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="graphqlRemoveSimpleProductFromCartPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlRemoveSimpleProductFromCartPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlRemoveSimpleProductFromCartPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="graphqlSetBillingAddressOnCartPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlSetBillingAddressOnCartPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlSetBillingAddressOnCartPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="graphqlSetShippingAddressOnCartPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlSetShippingAddressOnCartPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlSetShippingAddressOnCartPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="graphqlUpdateConfigurableProductQtyInCartPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlUpdateConfigurableProductQtyInCartPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlUpdateConfigurableProductQtyInCartPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="graphqlUpdateSimpleProductQtyInCartPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlUpdateSimpleProductQtyInCartPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlUpdateSimpleProductQtyInCartPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> <elementProp name="graphqlUrlInfoByUrlKeyPercentage" elementType="Argument"> <stringProp name="Argument.name">graphqlUrlInfoByUrlKeyPercentage</stringProp> <stringProp name="Argument.value">${__P(graphqlUrlInfoByUrlKeyPercentage,0)}</stringProp> @@ -39803,130 +39843,6 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Product Detail by product_name" enabled="true"> - <intProp name="ThroughputController.style">1</intProp> - <boolProp name="ThroughputController.perThread">false</boolProp> - <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlGetProductDetailByProductNamePercentage}</stringProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> - <hashTree> - <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> - <stringProp name="script"> -var testLabel = "${testLabel}" ? " (${testLabel})" : ""; -if (testLabel - && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' -) { - if (sampler.getName().indexOf(testLabel) == -1) { - sampler.setName(sampler.getName() + testLabel); - } -} else if (sampler.getName().indexOf("SetUp - ") == -1) { - sampler.setName("SetUp - " + sampler.getName()); -} - </stringProp> - <stringProp name="scriptLanguage">javascript</stringProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> - <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> - <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Get Product Detail by product_name"); - </stringProp> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - </BeanShellSampler> - <hashTree/> - - <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> - <collectionProp name="HeaderManager.headers"> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Content-Type</stringProp> - <stringProp name="Header.value">application/json</stringProp> - </elementProp> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Accept</stringProp> - <stringProp name="Header.value">*/*</stringProp> - </elementProp> - </collectionProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> - <hashTree/> - - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> - <stringProp name="BeanShellSampler.query"> -import java.util.Random; - -Random random = new Random(); -if (${seedForRandom} > 0) { - random.setSeed(${seedForRandom} + ${__threadNum}); -} - -vars.putObject("randomIntGenerator", random); - </stringProp> - <stringProp name="BeanShellSampler.filename"/> - <stringProp name="BeanShellSampler.parameters"/> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - </BeanShellSampler> - <hashTree/> - - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> - <stringProp name="BeanShellSampler.query"> -import java.util.Random; - -Random random = vars.getObject("randomIntGenerator"); -number = random.nextInt(props.get("configurable_products_list").size()); -product = props.get("configurable_products_list").get(number); - -vars.put("product_url_key", product.get("url_key")); -vars.put("product_id", product.get("id")); -vars.put("product_name", product.get("title")); -vars.put("product_uenc", product.get("uenc")); -vars.put("product_sku", product.get("sku")); - </stringProp> - <stringProp name="BeanShellSampler.filename"/> - <stringProp name="BeanShellSampler.parameters"/> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> - <hashTree/> - - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Product Detail by product_name" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_product_detail_by_product_name.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - </hashTree> - - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Product Search by text and category_id" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> @@ -40583,11 +40499,11 @@ vars.putObject("category", categories[number]); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Add Simple Product To Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Create Empty Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlAddSimpleProductToCartPercentage}</stringProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlCreateEmptyCartPercentage}</stringProp> <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> <hashTree> <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> @@ -40608,7 +40524,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Add Simple Product To Cart"); + vars.put("testLabel", "Create Empty Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -40646,26 +40562,118 @@ vars.putObject("randomIntGenerator", random); </BeanShellSampler> <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> - <stringProp name="BeanShellSampler.query"> -import java.util.Random; - -Random random = vars.getObject("randomIntGenerator"); -number = random.nextInt(props.get("simple_products_list").size()); -product = props.get("simple_products_list").get(number); + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> -vars.put("product_url_key", product.get("url_key")); -vars.put("product_id", product.get("id")); -vars.put("product_name", product.get("title")); -vars.put("product_uenc", product.get("uenc")); -vars.put("product_sku", product.get("sku")); - </stringProp> - <stringProp name="BeanShellSampler.filename"/> - <stringProp name="BeanShellSampler.parameters"/> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Empty Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlGetEmptyCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "Get Empty Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> @@ -40702,8 +40710,1775 @@ vars.put("product_sku", product.get("sku")); <stringProp name="SUBJECT">BODY</stringProp> </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1901638450">{"data":{"cart":{"items":[]}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Set Shipping Address On Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlSetShippingAddressOnCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "Set Shipping Address On Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Shipping Address On Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n setShippingAddressesOnCart(\n input: {\n cart_id: \"${quote_id}\"\n shipping_addresses: [\n {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n ]\n }\n ) {\n cart {\n shipping_addresses {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_shipping_address_on_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1671866339">{"data":{"setShippingAddressesOnCart":{"cart":{"shipping_addresses":[{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"SHIPPING"}]}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Set Billing Address On Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlSetBillingAddressOnCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "Set Billing Address On Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Billing Address On Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_billing_address_on_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1147076914">{"data":{"setBillingAddressOnCart":{"cart":{"billing_address":{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"BILLING"}}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Add Simple Product To Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlAddSimpleProductToCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "Add Simple Product To Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("simple_products_list").size()); +product = props.get("simple_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Simple Product To Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_simple_product_to_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1421843282">addSimpleProductsToCart</stringProp> + <stringProp name="-1173443935">"sku":"${product_sku}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Add Configurable Product To Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlAddConfigurableProductToCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "Add Configurable Product To Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("configurable_products_list").size()); +product = props.get("configurable_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract Configurable Product option" enabled="true"> + <stringProp name="VAR">product_option</stringProp> + <stringProp name="JSONPATH">$.data.products.items[0].variants[0].product.sku</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/extract_configurable_product_option.jmx</stringProp></com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Configurable Product To Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_configurable_product_to_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1421843282">addConfigurableProductsToCart</stringProp> + <stringProp name="675049292">"sku":"${product_option}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Update Simple Product Qty In Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlUpdateSimpleProductQtyInCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "Update Simple Product Qty In Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("simple_products_list").size()); +product = props.get("simple_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Simple Product To Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_simple_product_to_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1421843282">addSimpleProductsToCart</stringProp> + <stringProp name="-1173443935">"sku":"${product_sku}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product qty In Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/update_simple_product_qty_in_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Update Configurable Product Qty In Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlUpdateConfigurableProductQtyInCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "Update Configurable Product Qty In Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("configurable_products_list").size()); +product = props.get("configurable_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract Configurable Product option" enabled="true"> + <stringProp name="VAR">product_option</stringProp> + <stringProp name="JSONPATH">$.data.products.items[0].variants[0].product.sku</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/extract_configurable_product_option.jmx</stringProp></com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Configurable Product To Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_configurable_product_to_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1421843282">addConfigurableProductsToCart</stringProp> + <stringProp name="675049292">"sku":"${product_option}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product qty In Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/update_configurable_product_qty_in_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Remove Simple Product From Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlRemoveSimpleProductFromCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "Remove Simple Product From Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> </hashTree> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("simple_products_list").size()); +product = props.get("simple_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Simple Product To Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> @@ -40780,93 +42555,242 @@ vars.put("product_sku", product.get("sku")); <stringProp name="SUBJECT">BODY</stringProp> </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> <hashTree/> - </hashTree> - - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product qty In Cart" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/update_simple_product_qty_in_cart.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Simple Product From Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_simple_product_from_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1452665323">{"data":{"removeItemFromCart":{"cart":{"items":[]}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Remove Configurable Product From Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlRemoveConfigurableProductFromCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "Remove Configurable Product From Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">8</intProp> + <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Billing Address On Cart" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_billing_address_on_cart.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="1147076914">{"data":{"setBillingAddressOnCart":{"cart":{"billing_address":{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"BILLING"}}}}}</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">8</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("configurable_products_list").size()); +product = props.get("configurable_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Shipping Address On Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n setShippingAddressesOnCart(\n input: {\n cart_id: \"${quote_id}\"\n shipping_addresses: [\n {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n ]\n }\n ) {\n cart {\n shipping_addresses {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -40885,27 +42809,36 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_shipping_address_on_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-1671866339">{"data":{"setShippingAddressesOnCart":{"cart":{"shipping_addresses":[{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"SHIPPING"}]}}}}</stringProp> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">8</intProp> + <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> - </hashTree> + + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract Configurable Product option" enabled="true"> + <stringProp name="VAR">product_option</stringProp> + <stringProp name="JSONPATH">$.data.products.items[0].variants[0].product.sku</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/extract_configurable_product_option.jmx</stringProp></com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Payment Method On Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Configurable Product To Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n setPaymentMethodOnCart(input: {\n cart_id: \"${quote_id}\", \n payment_method: {\n code: \"checkmo\"\n }\n }) {\n cart {\n selected_payment_method {\n code\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -40924,27 +42857,28 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_payment_method_on_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_configurable_product_to_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-1830199373">{"data":{"setPaymentMethodOnCart":{"cart":{"selected_payment_method":{"code":"checkmo"}}}}}</stringProp> + <stringProp name="1421843282">addConfigurableProductsToCart</stringProp> + <stringProp name="675049292">"sku":"${product_option}"</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">8</intProp> + <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Current Shipping Address" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n shipping_addresses {\n address_id\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -40963,59 +42897,29 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_current_shipping_address.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">address_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.shipping_addresses[0].address_id</stringProp> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> <stringProp name="DEFAULT"/> <stringProp name="VARIABLE"/> <stringProp name="SUBJECT">BODY</stringProp> </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> <hashTree/> - </hashTree> - - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Shipping Method On Cart" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n setShippingMethodsOnCart(input: \n {\n cart_id: \"${quote_id}\", \n shipping_methods: [{\n cart_address_id: ${address_id}\n carrier_code: \"flatrate\"\n method_code: \"flatrate\"\n }]\n }) {\n cart {\n shipping_addresses {\n selected_shipping_method {\n carrier_code\n method_code\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_shipping_method_on_cart.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="644143859">{"data":{"setShippingMethodsOnCart":{"cart":{"shipping_addresses":[{"selected_shipping_method":{"carrier_code":"flatrate","method_code":"flatrate"}}]}}}}</stringProp> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">8</intProp> + <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Simple Product From Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Configurable Product From Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> @@ -41040,7 +42944,7 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_simple_product_from_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_configurable_product_from_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> @@ -41056,11 +42960,11 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Add Configurable Product To Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Checkout By Guest" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlAddConfigurableProductToCartPercentage}</stringProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlCheckoutByGuestPercentage}</stringProp> <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> <hashTree> <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> @@ -41081,7 +42985,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Add Configurable Product To Cart"); + vars.put("testLabel", "Checkout By Guest"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -41119,33 +43023,13 @@ vars.putObject("randomIntGenerator", random); </BeanShellSampler> <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> - <stringProp name="BeanShellSampler.query"> -import java.util.Random; - -Random random = vars.getObject("randomIntGenerator"); -number = random.nextInt(props.get("configurable_products_list").size()); -product = props.get("configurable_products_list").get(number); - -vars.put("product_url_key", product.get("url_key")); -vars.put("product_id", product.get("id")); -vars.put("product_name", product.get("title")); -vars.put("product_uenc", product.get("uenc")); -vars.put("product_sku", product.get("sku")); - </stringProp> - <stringProp name="BeanShellSampler.filename"/> - <stringProp name="BeanShellSampler.parameters"/> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> - <hashTree/> - - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41164,36 +43048,35 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> - - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract Configurable Product option" enabled="true"> - <stringProp name="VAR">product_option</stringProp> - <stringProp name="JSONPATH">$.data.products.items[0].variants[0].product.sku</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/extract_configurable_product_option.jmx</stringProp></com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> - </hashTree> + </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Empty Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41212,26 +43095,47 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_empty_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> - <stringProp name="VAR">quote_id</stringProp> - <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1901638450">{"data":{"cart":{"items":[]}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Configurable Product To Cart" enabled="true"> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("configurable_products_list").size()); +product = props.get("configurable_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41250,28 +43154,36 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_configurable_product_to_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1421843282">addConfigurableProductsToCart</stringProp> - <stringProp name="675049292">"sku":"${product_option}"</stringProp> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> - </hashTree> + + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract Configurable Product option" enabled="true"> + <stringProp name="VAR">product_option</stringProp> + <stringProp name="JSONPATH">$.data.products.items[0].variants[0].product.sku</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/extract_configurable_product_option.jmx</stringProp></com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Configurable Product To Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41290,26 +43202,48 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_configurable_product_to_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">item_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1421843282">addConfigurableProductsToCart</stringProp> + <stringProp name="675049292">"sku":"${product_option}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product qty In Cart" enabled="true"> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("simple_products_list").size()); +product = props.get("simple_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Simple Product To Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41328,16 +43262,17 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/update_configurable_product_qty_in_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_simple_product_to_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> + <stringProp name="1421843282">addSimpleProductsToCart</stringProp> + <stringProp name="-1173443935">"sku":"${product_sku}"</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">8</intProp> + <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> </hashTree> @@ -41535,45 +43470,6 @@ vars.put("product_sku", product.get("sku")); </ResponseAssertion> <hashTree/> </hashTree> - - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Configurable Product From Cart" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_configurable_product_from_cart.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="1452665323">{"data":{"removeItemFromCart":{"cart":{"items":[]}}}}</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">8</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> </hashTree> </hashTree> From b881a5d98db719eae436d80965ea41365b53295e Mon Sep 17 00:00:00 2001 From: Shikha Mishra <shikhamishra@cedcoss.com> Date: Fri, 12 Apr 2019 00:41:22 +0530 Subject: [PATCH 468/603] Fixed #22223 Missing/Wrong data display on downloadable report table reports>downloads in BO --- .../ResourceModel/Product/Downloads/Collection.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php index 1985db0b90e2a..a7932e8a11f81 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php @@ -97,4 +97,15 @@ public function addFieldToFilter($field, $condition = null) } return $this; } + + /** + * Get SQL for get record count without left JOINs and group + * + * @return \Magento\Framework\DB\Select + */ + public function getSelectCountSql() { + $countSelect = parent::getSelectCountSql(); + $countSelect->reset(\Zend\Db\Sql\Select::GROUP); + return $countSelect; + } } From 4d84b348c26b4695ec47d9304bb6c83b124306cc Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Thu, 11 Apr 2019 15:18:07 -0500 Subject: [PATCH 469/603] MC-15824: Create new GraphQL script for our benchmark - part 3 --- setup/performance-toolkit/benchmark.jmx | 314 +----------------------- 1 file changed, 8 insertions(+), 306 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 760cba726def6..7207dd53be92d 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -40872,7 +40872,7 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Empty Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> @@ -40897,24 +40897,16 @@ vars.putObject("randomIntGenerator", random); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_empty_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">item_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> + <stringProp name="1901638450">{"data":{"cart":{"items":[]}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> + <intProp name="Assertion.test_type">8</intProp> </ResponseAssertion> <hashTree/> </hashTree> @@ -41070,7 +41062,7 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Empty Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> @@ -41095,24 +41087,16 @@ vars.putObject("randomIntGenerator", random); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_empty_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">item_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> + <stringProp name="1901638450">{"data":{"cart":{"items":[]}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> + <intProp name="Assertion.test_type">8</intProp> </ResponseAssertion> <hashTree/> </hashTree> @@ -41268,53 +41252,6 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">item_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> <stringProp name="BeanShellSampler.query"> import java.util.Random; @@ -41487,53 +41424,6 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">item_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> <stringProp name="BeanShellSampler.query"> import java.util.Random; @@ -41754,53 +41644,6 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">item_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> <stringProp name="BeanShellSampler.query"> import java.util.Random; @@ -42059,53 +41902,6 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">item_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> <stringProp name="BeanShellSampler.query"> import java.util.Random; @@ -42412,53 +42208,6 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">item_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> <stringProp name="BeanShellSampler.query"> import java.util.Random; @@ -42717,53 +42466,6 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">item_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> <stringProp name="BeanShellSampler.query"> import java.util.Random; From 184191f0d3e2dd1f26dc166c1e3295b998baba25 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 11 Apr 2019 15:52:37 -0500 Subject: [PATCH 470/603] MAGETWO-93628: Shopping cart is emptied after reset password procedure --- app/code/Magento/Customer/Model/AccountManagement.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 1806ea05f2fea..58a527769df78 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -1070,7 +1070,10 @@ public function validate(CustomerInterface $customer) $result = $this->getEavValidator()->isValid($customerModel); if ($result === false && is_array($this->getEavValidator()->getMessages())) { return $validationResults->setIsValid(false)->setMessages( - array_merge(...$this->getEavValidator()->getMessages()) + call_user_func_array( + 'array_merge', + $this->getEavValidator()->getMessages() + ) ); } return $validationResults->setIsValid(true)->setMessages([]); From 9e24d22ac0c6ff6afedefadc9401da6907980d48 Mon Sep 17 00:00:00 2001 From: Ansari <ziyaurrahman@krishtechnolabs.com> Date: Fri, 12 Apr 2019 12:39:19 +0530 Subject: [PATCH 471/603] Resolved Alignment Issue While Editing Order Data containing Downlodable Products #20917 --- .../templates/product/composite/fieldset/downloadable.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Downloadable/view/adminhtml/templates/product/composite/fieldset/downloadable.phtml b/app/code/Magento/Downloadable/view/adminhtml/templates/product/composite/fieldset/downloadable.phtml index c86eb56a39008..79e93abf58b99 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/templates/product/composite/fieldset/downloadable.phtml +++ b/app/code/Magento/Downloadable/view/adminhtml/templates/product/composite/fieldset/downloadable.phtml @@ -29,7 +29,7 @@ value="<?= /* @escapeNotVerified */ $_link->getId() ?>" <?= /* @escapeNotVerified */ $block->getLinkCheckedValue($_link) ?> price="<?= /* @escapeNotVerified */ $block->getCurrencyPrice($_link->getPrice()) ?>"/> <?php endif; ?> - <label for="links_<?= /* @escapeNotVerified */ $_link->getId() ?>" class="label"> + <label for="links_<?= /* @escapeNotVerified */ $_link->getId() ?>" class="label admin__field-label"> <?= $block->escapeHtml($_link->getTitle()) ?> <?php if ($_link->getSampleFile() || $_link->getSampleUrl()): ?>  (<a href="<?= /* @escapeNotVerified */ $block->getLinkSampleUrl($_link) ?>" <?= $block->getIsOpenInNewWindow()?'onclick="this.target=\'_blank\'"':'' ?>><?= /* @escapeNotVerified */ __('sample') ?></a>) From 6c14bd8f4fb4e78044906b483d7e53074b648227 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 12 Apr 2019 12:28:08 +0300 Subject: [PATCH 472/603] magento/magento2#20832: Static test fix. --- .../Magento/luma/Magento_Theme/web/css/source/_module.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less index f45a6ee945c0f..dfcc51e0a0a26 100644 --- a/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less @@ -112,8 +112,8 @@ font-size: @font-size__base; margin: 0 0 0 15px; - &.customer-welcome{ - margin: 0 0 0 5px; + &.customer-welcome { + margin: 0 0 0 5px; } > a { From 204675e48423e7472761373cebab698787baffdc Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 12 Apr 2019 13:30:56 +0300 Subject: [PATCH 473/603] magento/magento2#20182: Static test fix. --- .../Magento/Framework/App/Test/Unit/DocRootLocatorTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/internal/Magento/Framework/App/Test/Unit/DocRootLocatorTest.php b/lib/internal/Magento/Framework/App/Test/Unit/DocRootLocatorTest.php index fd6c1f208080a..ef4152ba2e49e 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/DocRootLocatorTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/DocRootLocatorTest.php @@ -8,6 +8,9 @@ use Magento\Framework\App\DocRootLocator; +/** + * Test for Magento\Framework\App\DocRootLocator class. + */ class DocRootLocatorTest extends \PHPUnit\Framework\TestCase { /** From 3b2f83a295f7fcb37b4cc385951cc9c584e5c381 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 12 Apr 2019 13:49:27 +0300 Subject: [PATCH 474/603] magento/magento2#22210: Static tests fix. --- .../Product/Edit/Tab/Attributes/Extend.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/Extend.php b/app/code/Magento/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/Extend.php index 4654144ce6873..a768e2450bfe8 100644 --- a/app/code/Magento/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/Extend.php +++ b/app/code/Magento/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/Extend.php @@ -4,13 +4,13 @@ * See COPYING.txt for license details. */ +namespace Magento\Bundle\Block\Adminhtml\Catalog\Product\Edit\Tab\Attributes; + /** - * Bundle Extended Attribures Block + * Bundle Extended Attribures Block. * - * @author Magento Core Team <core@magentocommerce.com> + * @author Magento Core Team <core@magentocommerce.com> */ -namespace Magento\Bundle\Block\Adminhtml\Catalog\Product\Edit\Tab\Attributes; - class Extend extends \Magento\Catalog\Block\Adminhtml\Form\Renderer\Fieldset\Element { /** @@ -85,6 +85,8 @@ public function getParentElementHtml() } /** + * Get options. + * * @return array */ public function getOptions() @@ -106,6 +108,8 @@ public function getOptions() } /** + * Is disabled field. + * * @return bool */ public function isDisabledField() @@ -118,6 +122,8 @@ public function isDisabledField() } /** + * Get product. + * * @return mixed */ public function getProduct() @@ -129,6 +135,8 @@ public function getProduct() } /** + * Get extended element. + * * @param string $switchAttributeCode * @return \Magento\Framework\Data\Form\Element\Select * @throws \Magento\Framework\Exception\LocalizedException From d189b695f831c099cb050585e76c42d3894ca324 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 12 Apr 2019 14:49:46 +0300 Subject: [PATCH 475/603] magento/magento2#22073: Static test fix. --- .../Observer/SaveDownloadableOrderItemObserver.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php index 19339e4484ef6..7c1d2748a3e9c 100644 --- a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php +++ b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php @@ -9,6 +9,8 @@ use Magento\Store\Model\ScopeInterface; /** + * Saves data from order to purchased links. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SaveDownloadableOrderItemObserver implements ObserverInterface @@ -159,7 +161,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) \Magento\Sales\Model\Order\Item::STATUS_PENDING == $orderStatusToEnableItem ? \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_AVAILABLE : \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_PENDING - )->setCreatedAt( + )->setCreatedAt( $orderItem->getCreatedAt() )->setUpdatedAt( $orderItem->getUpdatedAt() @@ -173,6 +175,8 @@ public function execute(\Magento\Framework\Event\Observer $observer) } /** + * Create purchased model. + * * @return \Magento\Downloadable\Model\Link\Purchased */ protected function _createPurchasedModel() @@ -181,6 +185,8 @@ protected function _createPurchasedModel() } /** + * Create product model. + * * @return \Magento\Catalog\Model\Product */ protected function _createProductModel() @@ -189,6 +195,8 @@ protected function _createProductModel() } /** + * Create purchased item model. + * * @return \Magento\Downloadable\Model\Link\Purchased\Item */ protected function _createPurchasedItemModel() @@ -197,6 +205,8 @@ protected function _createPurchasedItemModel() } /** + * Create items collection. + * * @return \Magento\Downloadable\Model\ResourceModel\Link\Purchased\Item\Collection */ protected function _createItemsCollection() From b39550ae4e947da335cea2e836005fc000b0082a Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 12 Apr 2019 15:14:39 +0300 Subject: [PATCH 476/603] magento/magento2#/19806: Static test fix. --- app/code/Magento/Downloadable/Model/SampleRepository.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Downloadable/Model/SampleRepository.php b/app/code/Magento/Downloadable/Model/SampleRepository.php index 98af48d1df993..07c7631fade13 100644 --- a/app/code/Magento/Downloadable/Model/SampleRepository.php +++ b/app/code/Magento/Downloadable/Model/SampleRepository.php @@ -23,6 +23,7 @@ /** * Class SampleRepository + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SampleRepository implements \Magento\Downloadable\Api\SampleRepositoryInterface @@ -100,7 +101,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function getList($sku) { @@ -209,6 +210,8 @@ public function save( } /** + * Save sample. + * * @param \Magento\Catalog\Api\Data\ProductInterface $product * @param SampleInterface $sample * @param bool $isGlobalScopeContent @@ -257,6 +260,8 @@ protected function saveSample( } /** + * Update sample. + * * @param \Magento\Catalog\Api\Data\ProductInterface $product * @param SampleInterface $sample * @param bool $isGlobalScopeContent @@ -319,7 +324,7 @@ protected function updateSample( } /** - * {@inheritdoc} + * @inheritdoc */ public function delete($id) { From 49d5454b518332b8d95b91b66b75fa1399c63a8f Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 12 Apr 2019 17:12:41 +0300 Subject: [PATCH 477/603] magento/magento2#20968: Static test fix. --- app/code/Magento/Store/Test/Unit/Model/StoreTest.php | 3 ++- .../integration/testsuite/Magento/Store/Model/StoreTest.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Store/Test/Unit/Model/StoreTest.php b/app/code/Magento/Store/Test/Unit/Model/StoreTest.php index dddc6828eb961..a83ca833a15e0 100644 --- a/app/code/Magento/Store/Test/Unit/Model/StoreTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/StoreTest.php @@ -667,7 +667,8 @@ public function isCurrentlySecureDataProvider() 'unsecure request, no secure base url registered' => [false, 443, false, true, null], 'unsecure request, not using registered port' => [false, 80], 'unsecure request, using registered port, not using secure in frontend' => [false, 443, false, false], - 'unsecure request, no secure base url registered, not using secure in frontend' => [false, 443, false, false, null], + 'unsecure request, no secure base url registered, not using secure in frontend' => + [false, 443, false, false, null], 'unsecure request, not using registered port, not using secure in frontend' => [false, 80, false, false], ]; } diff --git a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php index 32862ed99c475..00de5544d8fb7 100644 --- a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php +++ b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php @@ -15,6 +15,7 @@ /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * phpcs:disable Magento2.Security.Superglobal */ class StoreTest extends \PHPUnit\Framework\TestCase { @@ -408,7 +409,7 @@ public function testSaveValidation($badStoreData) /** * @return array */ - public static function saveValidationDataProvider() + public function saveValidationDataProvider() { return [ 'empty store name' => [['name' => '']], From c4ecfdbcaabe16ffa1008068e2e63478b2b34a9f Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 12 Apr 2019 17:26:27 +0300 Subject: [PATCH 478/603] magento/magento2#/22201: Static test fix. --- app/code/Magento/Bundle/Block/Checkout/Cart/Item/Renderer.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Bundle/Block/Checkout/Cart/Item/Renderer.php b/app/code/Magento/Bundle/Block/Checkout/Cart/Item/Renderer.php index b117c127dff39..863f273225693 100644 --- a/app/code/Magento/Bundle/Block/Checkout/Cart/Item/Renderer.php +++ b/app/code/Magento/Bundle/Block/Checkout/Cart/Item/Renderer.php @@ -69,6 +69,7 @@ public function __construct( /** * Overloaded method for getting list of bundle options + * * Caches result in quote item, because it can be used in cart 'recent view' and on same page in cart checkout * * @return array From 260ca860fa6a7630f43731ca6336fab4f099b505 Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Fri, 12 Apr 2019 09:33:24 -0500 Subject: [PATCH 479/603] MC-15826: Create new GraphQL script for our benchmark - part 4 --- setup/performance-toolkit/benchmark.jmx | 84 ++++++++++++------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 7207dd53be92d..696b1964101a5 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -39225,7 +39225,7 @@ if (name == null) { <stringProp name="ThreadGroup.delay"/> <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/thread_group.jmx</stringProp></ThreadGroup> <hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get List of Products by category_id" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Get List of Products by category_id" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -39250,7 +39250,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Get List of Products by category_id"); + vars.put("testLabel", "GraphQL Get List of Products by category_id"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -39347,7 +39347,7 @@ vars.putObject("category", categories[number]); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Simple Product Details by product_url_key" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Get Simple Product Details by product_url_key" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -39372,7 +39372,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Get Simple Product Details by product_url_key"); + vars.put("testLabel", "GraphQL Get Simple Product Details by product_url_key"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -39471,7 +39471,7 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Simple Product Details by name" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Get Simple Product Details by name" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -39496,7 +39496,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Get Simple Product Details by name"); + vars.put("testLabel", "GraphQL Get Simple Product Details by name"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -39595,7 +39595,7 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Configurable Product Detail by product_url_key" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Get Configurable Product Detail by product_url_key" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -39620,7 +39620,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Get Configurable Product Detail by product_url_key"); + vars.put("testLabel", "GraphQL Get Configurable Product Detail by product_url_key"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -39719,7 +39719,7 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Configurable Product Detail by name" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Get Configurable Product Detail by name" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -39744,7 +39744,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Get Configurable Product Detail by name"); + vars.put("testLabel", "GraphQL Get Configurable Product Detail by name"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -39843,7 +39843,7 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Product Search by text and category_id" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Get Product Search by text and category_id" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -39868,7 +39868,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Get Product Search by text and category_id"); + vars.put("testLabel", "GraphQL Get Product Search by text and category_id"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -39986,7 +39986,7 @@ if (totalCount == null) { </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Category List by category_id" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Get Category List by category_id" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -40011,7 +40011,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Get Category List by category_id"); + vars.put("testLabel", "GraphQL Get Category List by category_id"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -40134,7 +40134,7 @@ function assertCategoryChildren(category, response) { </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Url Info by url_key" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Get Url Info by url_key" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -40159,7 +40159,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Get Url Info by url_key"); + vars.put("testLabel", "GraphQL Get Url Info by url_key"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -40257,7 +40257,7 @@ vars.putObject("category", categories[number]); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Cms Page by id" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Get Cms Page by id" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -40282,7 +40282,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Get Cms Page by id"); + vars.put("testLabel", "GraphQL Get Cms Page by id"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -40377,7 +40377,7 @@ vars.put("cms_page_id", cmsPages[number].id); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Navigation Menu by category_id" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Get Navigation Menu by category_id" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -40402,7 +40402,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Get Navigation Menu by category_id"); + vars.put("testLabel", "GraphQL Get Navigation Menu by category_id"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -40499,7 +40499,7 @@ vars.putObject("category", categories[number]); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Create Empty Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Create Empty Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -40524,7 +40524,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Create Empty Cart"); + vars.put("testLabel", "GraphQL Create Empty Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -40611,7 +40611,7 @@ vars.putObject("randomIntGenerator", random); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Get Empty Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Get Empty Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -40636,7 +40636,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Get Empty Cart"); + vars.put("testLabel", "GraphQL Get Empty Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -40762,7 +40762,7 @@ vars.putObject("randomIntGenerator", random); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Set Shipping Address On Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Set Shipping Address On Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -40787,7 +40787,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Set Shipping Address On Cart"); + vars.put("testLabel", "GraphQL Set Shipping Address On Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -40952,7 +40952,7 @@ vars.putObject("randomIntGenerator", random); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Set Billing Address On Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Set Billing Address On Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -40977,7 +40977,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Set Billing Address On Cart"); + vars.put("testLabel", "GraphQL Set Billing Address On Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -41142,7 +41142,7 @@ vars.putObject("randomIntGenerator", random); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Add Simple Product To Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Add Simple Product To Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -41167,7 +41167,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Add Simple Product To Cart"); + vars.put("testLabel", "GraphQL Add Simple Product To Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -41314,7 +41314,7 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Add Configurable Product To Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Add Configurable Product To Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -41339,7 +41339,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Add Configurable Product To Cart"); + vars.put("testLabel", "GraphQL Add Configurable Product To Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -41534,7 +41534,7 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Update Simple Product Qty In Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Update Simple Product Qty In Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -41559,7 +41559,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Update Simple Product Qty In Cart"); + vars.put("testLabel", "GraphQL Update Simple Product Qty In Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -41792,7 +41792,7 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Update Configurable Product Qty In Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Update Configurable Product Qty In Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -41817,7 +41817,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Update Configurable Product Qty In Cart"); + vars.put("testLabel", "GraphQL Update Configurable Product Qty In Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -42098,7 +42098,7 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Remove Simple Product From Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Remove Simple Product From Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -42123,7 +42123,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Remove Simple Product From Cart"); + vars.put("testLabel", "GraphQL Remove Simple Product From Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -42356,7 +42356,7 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Remove Configurable Product From Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Remove Configurable Product From Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -42381,7 +42381,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Remove Configurable Product From Cart"); + vars.put("testLabel", "GraphQL Remove Configurable Product From Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -42662,7 +42662,7 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="Checkout By Guest" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Checkout By Guest" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> @@ -42687,7 +42687,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "Checkout By Guest"); + vars.put("testLabel", "GraphQL Checkout By Guest"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> From 101a82ed526e98193ba95cda96a055a75182ce71 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Fri, 12 Apr 2019 09:36:31 -0500 Subject: [PATCH 480/603] MQE-1492: Deliver weekly mtf-to-mftf PR - Skip QuickSearchWithTwoCharsEmptyResults --- .../CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml index 8c5ea9f8205c4..19db201e91f40 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml @@ -107,6 +107,9 @@ <testCaseId value="MC-14794"/> <group value="CatalogSearch"/> <group value="mtf_migrated"/> + <skip> + <issueId value="MC-15827"/> + </skip> </annotations> <executeJS function="var s = '$createSimpleProduct.name$'; var ret=s.substring(0,2); return ret;" stepKey="getFirstTwoLetters" before="searchStorefront"/> <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefront"> From ce3097f992dfa2c784be934dd29a1b9401a4f83d Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 12 Apr 2019 17:36:32 +0300 Subject: [PATCH 481/603] magento/magento2#22220: Static test fix. --- .../integration/testsuite/Magento/Sales/_files/order_list.php | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_list.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_list.php index 8a1da8e8a3eb1..99122d72df4b7 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/order_list.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_list.php @@ -9,6 +9,7 @@ use Magento\Sales\Model\Order\Address as OrderAddress; use Magento\Sales\Model\Order\Payment; +// phpcs:ignore Magento2.Security.IncludeFile require 'order.php'; /** @var Order $order */ /** @var Order\Payment $payment */ From f0831c7d4e225a8998601f11865c3ea05ccbd220 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Fri, 12 Apr 2019 18:18:32 +0300 Subject: [PATCH 482/603] MAGETWO-98947: UPS CGI url gateway to migrate from http to https - Added supress for static test; --- app/code/Magento/Ups/Model/Carrier.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index d3a0bb86b0496..0e2ce05f2d079 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -1528,6 +1528,7 @@ protected function _sendShipmentAcceptRequest(Element $shipmentConfirmResponse) $shippingLabelContent = (string)$response->ShipmentResults->PackageResults->LabelImage->GraphicImage; $trackingNumber = (string)$response->ShipmentResults->PackageResults->TrackingNumber; + // phpcs:ignore Magento2.Functions.DiscouragedFunction $result->setShippingLabelContent(base64_decode($shippingLabelContent)); $result->setTrackingNumber($trackingNumber); } From 87312d4b58e57f70962ebc7078dd87cf2a29ac6c Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Fri, 12 Apr 2019 11:36:08 -0500 Subject: [PATCH 483/603] GraphQL-564: [Checkout coverage] setGuestEmailOnCart mutation --- .../testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php index 648b8265ee674..31f60afc1331f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php @@ -226,7 +226,7 @@ public function testPlaceOrderWithOutOfStockProduct() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php */ - public function testPlaceOrderOfAnotherCustomerCart() + public function testPlaceOrderOfCustomerCart() { $reservedOrderId = 'test_quote'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); From 1834026df5298f91ff7fd746e458172a6d299d9b Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Fri, 12 Apr 2019 11:56:18 -0500 Subject: [PATCH 484/603] GraphQL-295: [Place order] Place order mutation -- fixes after merge with mainline --- .../GraphQl/CatalogInventory/AddProductToCartTest.php | 6 +++--- .../AddConfigurableProductToCartTest.php | 6 +++--- .../Quote/AddSimpleProductWithCustomOptionsToCartTest.php | 4 ++-- .../Quote/AddVirtualProductWithCustomOptionsToCartTest.php | 4 ++-- .../GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php | 2 +- .../GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php | 2 +- .../GraphQl/Quote/Guest/AddSimpleProductToCartTest.php | 4 ++-- .../GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php | 2 +- .../GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 86e71d9914fe3..99f1dc004c50f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -43,7 +43,7 @@ public function testAddProductIfQuantityIsNotAvailable() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $query = $this->getQuery($maskedQuoteId, $sku, $qty); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -62,7 +62,7 @@ public function testAddMoreProductsThatAllowed() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $query = $this->getQuery($maskedQuoteId, $sku, $qty); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -78,7 +78,7 @@ public function testAddSimpleProductToCartWithNegativeQty() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $query = $this->getQuery($maskedQuoteId, $sku, $qty); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php index e4ae59cc0d281..d22cd14a4ae26 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php @@ -41,7 +41,7 @@ public function testAddConfigurableProductToCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $query = $this->getQuery($maskedQuoteId, $variantSku, $qty); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); $cartItems = $response['addConfigurableProductsToCart']['cart']['items']; self::assertEquals($qty, $cartItems[0]['qty']); @@ -61,7 +61,7 @@ public function testAddProductIfQuantityIsNotAvailable() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $query = $this->getQuery($maskedQuoteId, $variantSku, $qty); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -77,7 +77,7 @@ public function testAddOutOfStockProduct() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $query = $this->getQuery($maskedQuoteId, $variantSku, $qty); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php index 6da1b2c9b54c9..f33ccce82fcb7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php @@ -86,7 +86,7 @@ public function testAddSimpleProductWithOptions() } QUERY; - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('items', $response['addSimpleProductsToCart']['cart']); self::assertCount(1, $response['addSimpleProductsToCart']['cart']); @@ -148,7 +148,7 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() 'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.' ); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php index 1e1ee91336107..ffd52bcf7fb15 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php @@ -86,7 +86,7 @@ public function testAddVirtualProductWithOptions() } QUERY; - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('items', $response['addVirtualProductsToCart']['cart']); self::assertCount(1, $response['addVirtualProductsToCart']['cart']); @@ -148,7 +148,7 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() 'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.' ); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php index 93782f93402e1..2604ec5f0a0f9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php @@ -221,7 +221,7 @@ public function testSetDisabledPaymentOnCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $methodCode); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php index e64bbf7a75449..0fc52443e86b9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php @@ -452,7 +452,7 @@ public function testSetShippingMethodOnAnEmptyCart() $carrierCode, $quoteAddressId ); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php index 3270449f3e8dd..25221b628e7fb 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php @@ -41,7 +41,7 @@ public function testAddSimpleProductToCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $query = $this->getQuery($maskedQuoteId, $sku, $qty); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['qty']); @@ -61,7 +61,7 @@ public function testAddProductToNonExistentCart() $maskedQuoteId = 'non_existent_masked_id'; $query = $this->getQuery($maskedQuoteId, $sku, $qty); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php index 33183f175e425..4ea7eac290f80 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php @@ -232,7 +232,7 @@ public function testSetDisabledPaymentOnCart() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $methodCode); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php index 72d6e02ffaadc..59f53d2ad6856 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php @@ -403,7 +403,7 @@ public function testSetShippingMethodOnAnEmptyCart() $carrierCode, $quoteAddressId ); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** From a74b0c1e0c4a57729620131ac1927b243f6556cf Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Fri, 12 Apr 2019 14:43:03 -0500 Subject: [PATCH 485/603] MAGETWO-93628: Shopping cart is emptied after reset password procedure --- app/code/Magento/Customer/Model/AccountManagement.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 58a527769df78..250d190f8fae7 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -705,6 +705,7 @@ public function resetPassword($email, $resetToken, $newPassword) if ($this->sessionManager->isSessionExists()) { //delete old session and move data to the new session //use this instead of $this->sessionManager->regenerateId because last one doesn't delete old session + // phpcs:ignore Magento2.Functions.DiscouragedFunction session_regenerate_id(true); } $this->customerRepository->save($customer); From 78f02fa51cd4322bd89785c95805ca4b7359443a Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Sat, 13 Apr 2019 09:27:02 +0300 Subject: [PATCH 486/603] magento/graphql-ce#540: Replace deprecated fixture --- .../Ups/SetUpsShippingMethodsOnCartTest.php | 160 ++++++++++++++---- 1 file changed, 124 insertions(+), 36 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index d4e6448eb5fbf..3e2d6d23f6c2d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -55,20 +55,21 @@ protected function setUp() } /** + * Set "Next Day Air Early AM" UPS shipping method + * * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php - * - * @param string $carrierMethodCode - * @param string $carrierMethodLabel - * @dataProvider availableForCartShippingMethods */ - public function testSetAvailableForCartUpsShippingMethod(string $carrierMethodCode, string $carrierMethodLabel) + public function testSetNextDayAirEarlyAmUpsShippingMethod() { $quoteReservedId = 'test_quote'; + $carrierMethodCode = '1DM'; + $carrierMethodLabel = 'Next Day Air Early AM'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); @@ -91,20 +92,21 @@ public function testSetAvailableForCartUpsShippingMethod(string $carrierMethodCo } /** + * Set "Next Day Air" UPS shipping method + * * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php - * - * @param string $carrierMethodCode - * @param string $carrierMethodLabel - * @dataProvider notAvailableForCartShippingMethods */ - public function testSetNotAvailableForCartUpsShippingMethod(string $carrierMethodCode, string $carrierMethodLabel) + public function testSetNextDayAirUpsShippingMethod() { $quoteReservedId = 'test_quote'; + $carrierMethodCode = '1DA'; + $carrierMethodLabel = 'Next Day Air'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); @@ -115,8 +117,41 @@ public function testSetNotAvailableForCartUpsShippingMethod(string $carrierMetho $carrierMethodCode ); - $this->expectExceptionMessage( - "GraphQL response contains errors: Carrier with such method not found: " . self::CARRIER_CODE . ", " . $carrierMethodCode + $response = $this->sendRequestWithToken($query); + + $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses']; + $expectedResult = [ + 'carrier_code' => self::CARRIER_CODE, + 'method_code' => $carrierMethodCode, + 'label' => self::CARRIER_LABEL . ' - ' . $carrierMethodLabel, + ]; + self::assertEquals($addressesInformation[0]['selected_shipping_method'], $expectedResult); + } + + /** + * Set "2nd Day Air" UPS shipping method + * + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php + */ + public function testSet2ndDayAirUpsShippingMethod() + { + $quoteReservedId = 'test_quote'; + $carrierMethodCode = '2DA'; + $carrierMethodLabel = '2nd Day Air'; + + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); + $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); + + $query = $this->getQuery( + $maskedQuoteId, + $shippingAddressId, + self::CARRIER_CODE, + $carrierMethodCode ); $response = $this->sendRequestWithToken($query); @@ -131,56 +166,109 @@ public function testSetNotAvailableForCartUpsShippingMethod(string $carrierMetho } /** - * @return array + * Set "3 Day Select" UPS shipping method + * + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php */ - public function availableForCartShippingMethods(): array + public function testSet3DaySelectUpsShippingMethod() { - $shippingMethods = ['1DM', '1DA', '2DA', '3DS', 'GND']; + $quoteReservedId = 'test_quote'; + $carrierMethodCode = '3DS'; + $carrierMethodLabel = '3 Day Select'; - return $this->filterShippingMethodsByCodes($shippingMethods); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); + $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); + + $query = $this->getQuery( + $maskedQuoteId, + $shippingAddressId, + self::CARRIER_CODE, + $carrierMethodCode + ); + + $response = $this->sendRequestWithToken($query); + + $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses']; + $expectedResult = [ + 'carrier_code' => self::CARRIER_CODE, + 'method_code' => $carrierMethodCode, + 'label' => self::CARRIER_LABEL . ' - ' . $carrierMethodLabel, + ]; + self::assertEquals($addressesInformation[0]['selected_shipping_method'], $expectedResult); } /** - * @return array + * Set "Ground" UPS shipping method + * + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php */ - public function notAvailableForCartShippingMethods(): array + public function testSetGroundUpsShippingMethod() { - $shippingMethods = ['1DML', '1DAL', '1DAPI', '1DP', '1DPL', '2DM', '2DML', '2DAL', 'GNDCOM', 'GNDRES', 'STD', 'XPR', 'WXS', 'XPRL', 'XDM', 'XDML', 'XPD']; + $quoteReservedId = 'test_quote'; + $carrierMethodCode = 'GND'; + $carrierMethodLabel = 'Ground'; - return $this->filterShippingMethodsByCodes($shippingMethods); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); + $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); + + $query = $this->getQuery( + $maskedQuoteId, + $shippingAddressId, + self::CARRIER_CODE, + $carrierMethodCode + ); + + $response = $this->sendRequestWithToken($query); + + $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses']; + $expectedResult = [ + 'carrier_code' => self::CARRIER_CODE, + 'method_code' => $carrierMethodCode, + 'label' => self::CARRIER_LABEL . ' - ' . $carrierMethodLabel, + ]; + self::assertEquals($addressesInformation[0]['selected_shipping_method'], $expectedResult); } + + + + /** - * @param array $filter * @return array */ - private function filterShippingMethodsByCodes(array $filter):array + public function notAvailableForCartShippingMethods(): array { - $result = []; - foreach ($this->getAllUpsShippingMethods() as $shippingMethod) { - if (in_array($shippingMethod[0], $filter)) { - $result[] = $shippingMethod; - } - } - return $result; + $shippingMethods = ['1DML', '1DAL', '1DAPI', '1DP', '1DPL', '2DM', '2DML', '2DAL', 'GNDCOM', 'GNDRES', 'STD', 'XPR', 'WXS', 'XPRL', 'XDM', 'XDML', 'XPD']; + + return $this->filterShippingMethodsByCodes($shippingMethods); } private function getAllUpsShippingMethods():array { return [ - ['1DM', 'Next Day Air Early AM'], + ['1DM', 'Next Day Air Early AM'], // ['1DML', 'Next Day Air Early AM Letter'], - ['1DA', 'Next Day Air'], + ['1DA', 'Next Day Air'], // ['1DAL', 'Next Day Air Letter'], ['1DAPI', 'Next Day Air Intra (Puerto Rico)'], ['1DP', 'Next Day Air Saver'], ['1DPL', 'Next Day Air Saver Letter'], ['2DM', '2nd Day Air AM'], ['2DML', '2nd Day Air AM Letter'], - ['2DA', '2nd Day Air'], + ['2DA', '2nd Day Air'], // ['2DAL', '2nd Day Air Letter'], - ['3DS', '3 Day Select'], - ['GND', 'Ground'], + ['3DS', '3 Day Select'], // + ['GND', 'Ground'], // ['GNDCOM', 'Ground Commercial'], ['GNDRES', 'Ground Residential'], ['STD', 'Canada Standard'], From bf8e919b4bf203cc6caa59ceee668ff7eddc8a58 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sat, 13 Apr 2019 09:01:11 +0200 Subject: [PATCH 487/603] Code style fix --- .../Model/ResourceModel/Product/Downloads/Collection.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php index a7932e8a11f81..aeb0448f8e05a 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php @@ -103,7 +103,8 @@ public function addFieldToFilter($field, $condition = null) * * @return \Magento\Framework\DB\Select */ - public function getSelectCountSql() { + public function getSelectCountSql() + { $countSelect = parent::getSelectCountSql(); $countSelect->reset(\Zend\Db\Sql\Select::GROUP); return $countSelect; From 6dcd0e93317f796ccc89effb85616791dd243c74 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sat, 13 Apr 2019 13:45:36 +0200 Subject: [PATCH 488/603] Refactoring. Use action groups and config data --- ...ssertDashboardPageIsVisibleActionGroup.xml | 15 ++++++++++++ .../Test/Mftf/Data/BackendConfigData.xml | 24 +++++++++++++++++++ .../AdminUserLoginWithStoreCodeInUrlTest.xml | 8 +++---- ...refrontAssertStoreCodeInUrlActionGroup.xml | 13 ++++++++++ .../Test/StorefrontAddStoreCodeInUrlTest.xml | 13 ++++------ ...StorefrontClickOnHeaderLogoActionGroup.xml | 16 +++++++++++++ 6 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminAssertDashboardPageIsVisibleActionGroup.xml create mode 100644 app/code/Magento/Backend/Test/Mftf/Data/BackendConfigData.xml create mode 100644 app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontAssertStoreCodeInUrlActionGroup.xml create mode 100644 app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminAssertDashboardPageIsVisibleActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminAssertDashboardPageIsVisibleActionGroup.xml new file mode 100644 index 0000000000000..df22bb27d6b88 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminAssertDashboardPageIsVisibleActionGroup.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="AdminAssertDashboardPageIsVisibleActionGroup"> + <seeInCurrentUrl url="{{AdminDashboardPage.url}}" stepKey="seeDashboardUrl"/> + <see userInput="Dashboard" selector="{{AdminHeaderSection.pageTitle}}" stepKey="seeDashboardTitle"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Data/BackendConfigData.xml b/app/code/Magento/Backend/Test/Mftf/Data/BackendConfigData.xml new file mode 100644 index 0000000000000..4333446925474 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Data/BackendConfigData.xml @@ -0,0 +1,24 @@ +<?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="StorefrontDisableAddStoreCodeToUrls"> + <!-- Magento default value --> + <data key="path">web/url/use_store</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="StorefrontEnableAddStoreCodeToUrls"> + <data key="path">web/url/use_store</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> +</entities> diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml index a8f86f3309b5c..51ba1a142803d 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml @@ -17,13 +17,13 @@ <group value="mtf_migrated"/> </annotations> <before> - <magentoCLI command="config:set web/url/use_store 1" stepKey="addStoreCodeToUrl"/> + <magentoCLI command="config:set {{StorefrontEnableAddStoreCodeToUrls.path}} {{StorefrontEnableAddStoreCodeToUrls.value}}" stepKey="addStoreCodeToUrlEnable"/> </before> <after> - <magentoCLI command="config:set web/url/use_store 0" stepKey="addStoreCodeToUrlDisable"/> + <magentoCLI command="config:set {{StorefrontDisableAddStoreCodeToUrls.path}} {{StorefrontDisableAddStoreCodeToUrls.value}}" stepKey="addStoreCodeToUrlDisable"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <see userInput="Dashboard" selector="{{AdminHeaderSection.pageTitle}}" stepKey="seeDashboardTitle"/> + <actionGroup ref="AdminAssertDashboardPageIsVisibleActionGroup" stepKey="seeDashboardPage"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontAssertStoreCodeInUrlActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontAssertStoreCodeInUrlActionGroup.xml new file mode 100644 index 0000000000000..974526afbf21c --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontAssertStoreCodeInUrlActionGroup.xml @@ -0,0 +1,13 @@ +<?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="StorefrontAssertStoreCodeInUrlActionGroup"> + <seeInCurrentUrl url="{{StorefrontHomePage.url}}{{_defaultStore.code}}" stepKey="seeStoreCodeInURL"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml b/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml index b04267ef83d60..7bee46da1a226 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml @@ -17,16 +17,13 @@ <group value="mtf_migrated"/> </annotations> <before> - <magentoCLI command="config:set web/url/use_store 1" stepKey="addStoreCodeToUrl"/> + <magentoCLI command="config:set {{StorefrontEnableAddStoreCodeToUrls.path}} {{StorefrontEnableAddStoreCodeToUrls.value}}" stepKey="addStoreCodeToUrlEnable"/> </before> <after> - <magentoCLI command="config:set web/url/use_store 0" stepKey="addStoreCodeToUrlDisable"/> + <magentoCLI command="config:set {{StorefrontDisableAddStoreCodeToUrls.path}} {{StorefrontDisableAddStoreCodeToUrls.value}}" stepKey="addStoreCodeToUrlDisable"/> </after> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="gotToHomePage"/> - <waitForPageLoad stepKey="waitForHomePageLoaded1"/> - <click selector="{{StorefrontHeaderSection.logoLink}}" stepKey="clickOnLogo"/> - <waitForPageLoad stepKey="waitForHomePageLoaded2"/> - <seeInCurrentUrl url="{{StorefrontHomePage.url}}{{_defaultStore.code}}" stepKey="seeStoreCodeInURL"/> + <actionGroup ref="StorefrontClickOnHeaderLogoActionGroup" stepKey="clickOnStorefrontHeaderLogo"/> + <actionGroup ref="StorefrontAssertStoreCodeInUrlActionGroup" stepKey="seeStoreCodeInUrl"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml b/app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml new file mode 100644 index 0000000000000..6e45429b9e1e8 --- /dev/null +++ b/app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontClickOnHeaderLogoActionGroup"> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="gotToHomePage"/> + <waitForPageLoad stepKey="waitForHomePageLoaded1"/> + <click selector="{{StorefrontHeaderSection.logoLink}}" stepKey="clickOnLogo"/> + <waitForPageLoad stepKey="waitForHomePageLoaded2"/> + </actionGroup> +</actionGroups> From ae7179f7bee1b99597aee46da79f581a8a45a018 Mon Sep 17 00:00:00 2001 From: Oleg Volkov <sirwerwolf@gmail.com> Date: Sat, 13 Apr 2019 15:34:17 +0300 Subject: [PATCH 489/603] #21747 Fix catalog_product_flat_data attribute value for store during indexer --- .../Model/Indexer/Product/Flat/TableBuilder.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php index a3d958ea537e1..0865c311e7094 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php @@ -306,10 +306,11 @@ protected function _fillTemporaryTable( foreach ($columnsList as $columnName => $attribute) { $countTableName = 't' . $iterationNum++; $joinCondition = sprintf( - 'e.%3$s = %1$s.%3$s AND %1$s.attribute_id = %2$d AND %1$s.store_id = 0', + 'e.%3$s = %1$s.%3$s AND %1$s.attribute_id = %2$d AND (%1$s.store_id = %4$d OR %1$s.store_id = 0)', $countTableName, $attribute->getId(), - $metadata->getLinkField() + $metadata->getLinkField(), + $storeId ); $select->joinLeft( @@ -323,9 +324,10 @@ protected function _fillTemporaryTable( $columnValueName = $attributeCode . $valueFieldSuffix; if (isset($flatColumns[$columnValueName])) { $valueJoinCondition = sprintf( - 'e.%1$s = %2$s.option_id AND %2$s.store_id = 0', + 'e.%1$s = %2$s.option_id AND (%2$s.store_id = %3$d OR %2$s.store_id = 0)', $attributeCode, - $countTableName + $countTableName, + $storeId ); $selectValue->joinLeft( [ From 6124c6087c9f2c0c0b4ed3b7be27286c79b12d19 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sat, 13 Apr 2019 14:46:57 +0200 Subject: [PATCH 490/603] Refactoring. Use action groups and config data --- .../AdminForgotPasswordFormSection.xml | 4 +- ...AdminFillForgotPasswordFormActionGroup.xml | 17 +++++++ ...AdminOpenForgotPasswordPageActionGroup.xml | 16 +++++++ ...minSubmitForgotPasswordFormActionGroup.xml | 13 +++++ ...AssertAdminLoginPageMessageActionGroup.xml | 19 ++++++++ .../Test/AdminResetUserPasswordFailedTest.xml | 48 +++++++++++++++++++ .../Mftf/Test/ResetUserPasswordFailedTest.xml | 37 -------------- .../TestCase/ResetUserPasswordFailedTest.xml | 3 +- 8 files changed, 116 insertions(+), 41 deletions(-) create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillForgotPasswordFormActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenForgotPasswordPageActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminSubmitForgotPasswordFormActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml delete mode 100644 app/code/Magento/User/Test/Mftf/Test/ResetUserPasswordFailedTest.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminForgotPasswordFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminForgotPasswordFormSection.xml index 5c33369b38767..efaca22123354 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminForgotPasswordFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminForgotPasswordFormSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminForgotPasswordFormSection"> - <element name="email" type="input" selector="#email"/> - <element name="retrievePasswordButton" type="button" selector=".action-retrieve" timeout="30"/> + <element name="email" type="input" selector="#login-form input[name='email']"/> + <element name="retrievePasswordButton" type="button" selector="#login-form button[type='submit']" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillForgotPasswordFormActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillForgotPasswordFormActionGroup.xml new file mode 100644 index 0000000000000..01be51e72ec6d --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillForgotPasswordFormActionGroup.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="AdminFillForgotPasswordFormActionGroup"> + <arguments> + <argument name="email" type="string"/> + </arguments> + + <fillField selector="{{AdminForgotPasswordFormSection.email}}" userInput="{{email}}" stepKey="fillAdminEmail"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenForgotPasswordPageActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenForgotPasswordPageActionGroup.xml new file mode 100644 index 0000000000000..fa17c5a7f8b76 --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenForgotPasswordPageActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenForgotPasswordPageActionGroup"> + <amOnPage url="{{AdminLoginPage.url}}" stepKey="amOnAdminLoginPage"/> + <waitForPageLoad stepKey="waitForAdminLoginPage"/> + <click stepKey="clickForgotPasswordLink" selector="{{AdminLoginFormSection.forgotPasswordLink}}"/> + <waitForPageLoad stepKey="waitForAdminForgotPasswordPage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminSubmitForgotPasswordFormActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminSubmitForgotPasswordFormActionGroup.xml new file mode 100644 index 0000000000000..198bc713093ea --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminSubmitForgotPasswordFormActionGroup.xml @@ -0,0 +1,13 @@ +<?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="AdminSubmitForgotPasswordFormActionGroup"> + <click selector="{{AdminForgotPasswordFormSection.retrievePasswordButton}}" stepKey="clickOnRetrievePasswordButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.xml new file mode 100644 index 0000000000000..5535d2314a69f --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.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="AssertAdminLoginPageMessageActionGroup"> + <arguments> + <argument name="messageType" type="string"/> + <argument name="message" type="string"/> + </arguments> + + <waitForElementVisible selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" stepKey="waitForAdminLoginFormMessage" /> + <see userInput="{{message}}" selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" stepKey="seeAdminLoginFormMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml new file mode 100644 index 0000000000000..0d66ed38d4310 --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml @@ -0,0 +1,48 @@ +<?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="AdminResetUserPasswordFailedTest"> + <annotations> + <features value="User"/> + <title value="Admin user should not be able to trigger the password reset procedure twice"/> + <description value="Admin user should not be able to trigger the password reset procedure twice"/> + <group value="security"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <magentoCLI command="config:set {{AdminCaptchaDisableConfigData.path}} {{AdminCaptchaDisableConfigData.value}} " stepKey="disableAdminCaptcha"/> + </before> + <after> + <magentoCLI command="config:set {{AdminCaptchaEnableConfigData.path}} {{AdminCaptchaEnableConfigData.value}} " stepKey="enableAdminCaptcha"/> + </after> + + <!-- First attempt to reset password --> + <actionGroup ref="AdminOpenForgotPasswordPageActionGroup" stepKey="openAdminForgotPasswordPage1"/> + <actionGroup ref="AdminFillForgotPasswordFormActionGroup" stepKey="fillAdminForgotPasswordForm1"> + <argument name="email" value="customer@example.com"/> + </actionGroup> + <actionGroup ref="AdminSubmitForgotPasswordFormActionGroup" stepKey="submitAdminForgotPasswordForm1"/> + <actionGroup ref="AssertAdminLoginPageMessageActionGroup" stepKey="seeSuccessMessage"> + <argument name="messageType" value="success"/> + <argument name="message" value="We'll email you a link to reset your password."/> + </actionGroup> + + <!-- Second attempt to reset password --> + <actionGroup ref="AdminOpenForgotPasswordPageActionGroup" stepKey="openAdminForgotPasswordPage2"/> + <actionGroup ref="AdminFillForgotPasswordFormActionGroup" stepKey="fillAdminForgotPasswordForm2"> + <argument name="email" value="customer@example.com"/> + </actionGroup> + <actionGroup ref="AdminSubmitForgotPasswordFormActionGroup" stepKey="submitAdminForgotPasswordForm2"/> + <actionGroup ref="AssertAdminLoginPageMessageActionGroup" stepKey="seeErrorMessage"> + <argument name="messageType" value="error"/> + <argument name="message" value="We received too many requests for password resets. Please wait and try again later or contact hello@example.com."/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/User/Test/Mftf/Test/ResetUserPasswordFailedTest.xml b/app/code/Magento/User/Test/Mftf/Test/ResetUserPasswordFailedTest.xml deleted file mode 100644 index 3a614c91aeebc..0000000000000 --- a/app/code/Magento/User/Test/Mftf/Test/ResetUserPasswordFailedTest.xml +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="ResetUserPasswordFailedTest"> - <annotations> - <features value="User"/> - <title value="Admin user should not be able to trigger the password reset procedure twice"/> - <description value="Admin user should not be able to trigger the password reset procedure twice"/> - <group value="security"/> - <group value="mtf_migrated"/> - </annotations> - <before> - <magentoCLI command="config:set admin/captcha/enable 0" stepKey="disableAdminCaptcha"/> - </before> - - <amOnPage url="{{AdminLoginPage.url}}" stepKey="amOnAdminLoginPage"/> - <waitForPageLoad stepKey="waitForAdminLoginPage1"/> - <click stepKey="clickForgotPasswordLink1" selector="{{AdminLoginFormSection.forgotPasswordLink}}"/> - <fillField selector="{{AdminForgotPasswordFormSection.email}}" userInput="some@example.com" stepKey="fillAdminEmail1"/> - <click selector="{{AdminForgotPasswordFormSection.retrievePasswordButton}}" stepKey="clickOnRetrievePasswordButton1"/> - <waitForElementVisible selector="{{AdminUserLoginMessagesSection.successMessage}}" stepKey="waitForSuccessMessage" /> - <see stepKey="seeSuccessMessage" selector="{{AdminUserLoginMessagesSection.successMessage}}" userInput="We'll email you a link to reset your password."/> - <click stepKey="clickForgotPasswordLink2" selector="{{AdminLoginFormSection.forgotPasswordLink}}"/> - <waitForPageLoad stepKey="waitForAdminForgotPasswordPage2"/> - <fillField selector="{{AdminForgotPasswordFormSection.email}}" userInput="some@example.com" stepKey="fillAdminEmail2"/> - <click selector="{{AdminForgotPasswordFormSection.retrievePasswordButton}}" stepKey="clickOnRetrievePasswordButton2"/> - <waitForElementVisible selector="{{AdminUserLoginMessagesSection.errorMessage}}" stepKey="waitForFailMessage" /> - <see stepKey="seeErrorMessage" selector="{{AdminUserLoginMessagesSection.errorMessage}}" userInput="We received too many requests for password resets. Please wait and try again later or contact hello@example.com."/> - </test> -</tests> diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetUserPasswordFailedTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetUserPasswordFailedTest.xml index 229e980fed91f..f43469358aa9c 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetUserPasswordFailedTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/ResetUserPasswordFailedTest.xml @@ -8,10 +8,9 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Security\Test\TestCase\ResetUserPasswordFailedTest" summary="Prevent Locked Admin User to Log In into the Backend"> <variation name="ResetUserPasswordTestVariation1"> - <data name="tag" xsi:type="string">severity:S1</data> + <data name="tag" xsi:type="string">severity:S1,mftf_migrated:yes</data> <data name="customAdmin/dataset" xsi:type="string">custom_admin_with_default_role</data> <data name="attempts" xsi:type="string">2</data> - <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Security\Test\Constraint\AssertUserPasswordResetFailed" /> </variation> </testCase> From d52da79f976c3fa469c56c8c249d39f39452dfc6 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Sat, 13 Apr 2019 17:08:12 +0300 Subject: [PATCH 491/603] Vitalii Boiko: removed redundant subscriptions for catalog rules --- app/code/Magento/CatalogRule/etc/mview.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/code/Magento/CatalogRule/etc/mview.xml b/app/code/Magento/CatalogRule/etc/mview.xml index 35efe33461afc..657af387da226 100644 --- a/app/code/Magento/CatalogRule/etc/mview.xml +++ b/app/code/Magento/CatalogRule/etc/mview.xml @@ -16,11 +16,8 @@ <table name="catalog_product_entity" entity_column="entity_id" /> <table name="catalog_product_entity_datetime" entity_column="entity_id" /> <table name="catalog_product_entity_decimal" entity_column="entity_id" /> - <table name="catalog_product_entity_gallery" entity_column="entity_id" /> <table name="catalog_product_entity_int" entity_column="entity_id" /> - <table name="catalog_product_entity_text" entity_column="entity_id" /> <table name="catalog_product_entity_tier_price" entity_column="entity_id" /> - <table name="catalog_product_entity_varchar" entity_column="entity_id" /> <table name="catalog_category_product" entity_column="product_id" /> </subscriptions> </view> From bbca40240268c2d2f5a7f1c7196527d6b9151488 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Sat, 13 Apr 2019 17:38:24 +0300 Subject: [PATCH 492/603] Vitalii Boiko: revert varchar and text tables --- app/code/Magento/CatalogRule/etc/mview.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/CatalogRule/etc/mview.xml b/app/code/Magento/CatalogRule/etc/mview.xml index 657af387da226..9e5a1c866a842 100644 --- a/app/code/Magento/CatalogRule/etc/mview.xml +++ b/app/code/Magento/CatalogRule/etc/mview.xml @@ -17,7 +17,9 @@ <table name="catalog_product_entity_datetime" entity_column="entity_id" /> <table name="catalog_product_entity_decimal" entity_column="entity_id" /> <table name="catalog_product_entity_int" entity_column="entity_id" /> + <table name="catalog_product_entity_text" entity_column="entity_id" /> <table name="catalog_product_entity_tier_price" entity_column="entity_id" /> + <table name="catalog_product_entity_varchar" entity_column="entity_id" /> <table name="catalog_category_product" entity_column="product_id" /> </subscriptions> </view> From bed152b45be8c1c227434e66017f2f51a845770f Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Sat, 13 Apr 2019 16:20:14 +0300 Subject: [PATCH 493/603] magento/magento2#22317: CodeSniffer should not mark correctly aligned DocBlock elements as code style violation. --- .../Annotation/AnnotationFormatValidator.php | 40 +++++ .../MethodAnnotationStructureSniff.php | 1 + .../Annotation/MethodArgumentsSniff.php | 154 ++++++++++++++---- 3 files changed, 161 insertions(+), 34 deletions(-) diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php b/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php index 3f477f7ce5033..b102fa87b76a8 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php +++ b/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php @@ -249,6 +249,46 @@ public function validateTagGroupingFormat(File $phpcsFile, int $commentStartPtr) } } + /** + * Validates tag aligning format + * + * @param File $phpcsFile + * @param int $commentStartPtr + */ + public function validateTagAligningFormat(File $phpcsFile, int $commentStartPtr) : void + { + $tokens = $phpcsFile->getTokens(); + $noAlignmentPositions = []; + $actualPositions = []; + $stackPtr = null; + foreach ($tokens[$commentStartPtr]['comment_tags'] as $position => $tag) { + $content = $tokens[$tag]['content']; + if (preg_match('/^@/', $content) && ($tokens[$tag]['line'] === $tokens[$tag + 2]['line'])) { + $noAlignmentPositions[] = $tokens[$tag + 1]['column'] + 1; + $actualPositions[] = $tokens[$tag + 2]['column']; + $stackPtr = $stackPtr ?? $tag; + } + + } + + if (!$this->allTagsAligned($actualPositions) + && !$this->noneTagsAligned($actualPositions, $noAlignmentPositions)) { + $phpcsFile->addFixableError( + 'Tags visual alignment must be consistent', + $stackPtr, + 'MethodArguments' + ); + } + } + + private function allTagsAligned(array $actualPositions) { + return count(array_unique($actualPositions)) === 1; + } + + private function noneTagsAligned(array $actualPositions, array $noAlignmentPositions) { + return $actualPositions === $noAlignmentPositions; + } + /** * Validates extra newline before short description * diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodAnnotationStructureSniff.php b/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodAnnotationStructureSniff.php index 445671d245e03..f05ae64a170d7 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodAnnotationStructureSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodAnnotationStructureSniff.php @@ -75,6 +75,7 @@ public function process(File $phpcsFile, $stackPtr) $emptyTypeTokens ); $this->annotationFormatValidator->validateTagGroupingFormat($phpcsFile, $commentStartPtr); + $this->annotationFormatValidator->validateTagAligningFormat($phpcsFile, $commentStartPtr); } } } diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php b/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php index 879334d8c553b..5bd4667c4f4be 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php @@ -8,8 +8,8 @@ namespace Magento\Sniffs\Annotation; -use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; /** * Sniff to validate method arguments annotations @@ -42,7 +42,7 @@ class MethodArgumentsSniff implements Sniff /** * @inheritdoc */ - public function register() : array + public function register(): array { return [ T_FUNCTION @@ -55,7 +55,7 @@ public function register() : array * @param string $type * @return bool */ - private function isTokenBeforeClosingCommentTagValid(string $type) : bool + private function isTokenBeforeClosingCommentTagValid(string $type): bool { return in_array($type, $this->validTokensBeforeClosingCommentTag); } @@ -68,7 +68,7 @@ private function isTokenBeforeClosingCommentTagValid(string $type) : bool * @param int $stackPtr * @return bool */ - private function validateCommentBlockExists(File $phpcsFile, int $previousCommentClosePtr, int $stackPtr) : bool + private function validateCommentBlockExists(File $phpcsFile, int $previousCommentClosePtr, int $stackPtr): bool { $tokens = $phpcsFile->getTokens(); for ($tempPtr = $previousCommentClosePtr + 1; $tempPtr < $stackPtr; $tempPtr++) { @@ -85,7 +85,7 @@ private function validateCommentBlockExists(File $phpcsFile, int $previousCommen * @param string $type * @return bool */ - private function isInvalidType(string $type) : bool + private function isInvalidType(string $type): bool { return in_array(strtolower($type), $this->invalidTypes); } @@ -98,7 +98,7 @@ private function isInvalidType(string $type) : bool * @param int $closedParenthesisPtr * @return array */ - private function getMethodArguments(File $phpcsFile, int $openParenthesisPtr, int $closedParenthesisPtr) : array + private function getMethodArguments(File $phpcsFile, int $openParenthesisPtr, int $closedParenthesisPtr): array { $tokens = $phpcsFile->getTokens(); $methodArguments = []; @@ -121,7 +121,7 @@ private function getMethodArguments(File $phpcsFile, int $openParenthesisPtr, in * @param array $paramDefinitions * @return array */ - private function getMethodParameters(array $paramDefinitions) : array + private function getMethodParameters(array $paramDefinitions): array { $paramName = []; for ($i = 0; $i < count($paramDefinitions); $i++) { @@ -143,7 +143,7 @@ private function validateInheritdocAnnotationWithoutBracesExists( File $phpcsFile, int $previousCommentOpenPtr, int $previousCommentClosePtr - ) : bool { + ): bool { return $this->validateInheritdocAnnotationExists( $phpcsFile, $previousCommentOpenPtr, @@ -163,7 +163,7 @@ private function validateInheritdocAnnotationWithBracesExists( File $phpcsFile, int $previousCommentOpenPtr, int $previousCommentClosePtr - ) : bool { + ): bool { return $this->validateInheritdocAnnotationExists( $phpcsFile, $previousCommentOpenPtr, @@ -186,7 +186,7 @@ private function validateInheritdocAnnotationExists( int $previousCommentOpenPtr, int $previousCommentClosePtr, string $inheritdocAnnotation - ) : bool { + ): bool { $tokens = $phpcsFile->getTokens(); for ($ptr = $previousCommentOpenPtr; $ptr < $previousCommentClosePtr; $ptr++) { if (strtolower($tokens[$ptr]['content']) === $inheritdocAnnotation) { @@ -213,7 +213,7 @@ private function validateParameterAnnotationForArgumentExists( int $previousCommentOpenPtr, int $previousCommentClosePtr, int $stackPtr - ) : void { + ): void { if ($argumentsCount > 0 && $parametersCount === 0) { $inheritdocAnnotationWithoutBracesExists = $this->validateInheritdocAnnotationWithoutBracesExists( $phpcsFile, @@ -256,7 +256,7 @@ private function validateCommentBlockDoesnotHaveExtraParameterAnnotation( int $argumentsCount, int $parametersCount, int $stackPtr - ) : void { + ): void { if ($argumentsCount < $parametersCount && $argumentsCount > 0) { $phpcsFile->addFixableError( 'Extra @param found in method annotation', @@ -287,10 +287,10 @@ private function validateArgumentNameInParameterAnnotationExists( File $phpcsFile, array $methodArguments, array $paramDefinitions - ) : void { + ): void { $parameterNames = $this->getMethodParameters($paramDefinitions); if (!in_array($methodArguments[$ptr], $parameterNames)) { - $error = $methodArguments[$ptr]. ' parameter is missing in method annotation'; + $error = $methodArguments[$ptr] . ' parameter is missing in method annotation'; $phpcsFile->addFixableError($error, $stackPtr, 'MethodArguments'); } } @@ -310,7 +310,7 @@ private function validateParameterPresentInMethodSignature( array $methodArguments, File $phpcsFile, array $paramPointers - ) : void { + ): void { if (!in_array($paramDefinitionsArguments, $methodArguments)) { $phpcsFile->addFixableError( $paramDefinitionsArguments . ' parameter is missing in method arguments signature', @@ -333,7 +333,7 @@ private function validateParameterOrderIsCorrect( array $methodArguments, File $phpcsFile, array $paramPointers - ) : void { + ): void { $parameterNames = $this->getMethodParameters($paramDefinitions); $paramDefinitionsCount = count($paramDefinitions); for ($ptr = 0; $ptr < $paramDefinitionsCount; $ptr++) { @@ -342,7 +342,7 @@ private function validateParameterOrderIsCorrect( ) { if ($methodArguments[$ptr] != $parameterNames[$ptr]) { $phpcsFile->addFixableError( - $methodArguments[$ptr].' parameter is not in order', + $methodArguments[$ptr] . ' parameter is not in order', $paramPointers[$ptr], 'MethodArguments' ); @@ -366,12 +366,12 @@ private function validateDuplicateAnnotationDoesnotExists( array $paramPointers, File $phpcsFile, array $methodArguments - ) : void { + ): void { $argumentsCount = count($methodArguments); $parametersCount = count($paramPointers); if ($argumentsCount <= $parametersCount && $argumentsCount > 0) { $duplicateParameters = []; - for ($i = 0; $i < sizeof($paramDefinitions); $i++) { + for ($i = 0; $i < count($paramDefinitions); $i++) { if (isset($paramDefinitions[$i]['paramName'])) { $parameterContent = $paramDefinitions[$i]['paramName']; for ($j = $i + 1; $j < count($paramDefinitions); $j++) { @@ -408,7 +408,7 @@ private function validateParameterAnnotationFormatIsCorrect( array $methodArguments, array $paramDefinitions, array $paramPointers - ) : void { + ): void { switch (count($paramDefinitions)) { case 0: $phpcsFile->addFixableError( @@ -429,7 +429,7 @@ private function validateParameterAnnotationFormatIsCorrect( case 2: if ($this->isInvalidType($paramDefinitions[0])) { $phpcsFile->addFixableError( - $paramDefinitions[0].' is not a valid PHP type', + $paramDefinitions[0] . ' is not a valid PHP type', $paramPointers[$ptr], 'MethodArguments' ); @@ -451,7 +451,7 @@ private function validateParameterAnnotationFormatIsCorrect( ); if ($this->isInvalidType($paramDefinitions[0])) { $phpcsFile->addFixableError( - $paramDefinitions[0].' is not a valid PHP type', + $paramDefinitions[0] . ' is not a valid PHP type', $paramPointers[$ptr], 'MethodArguments' ); @@ -480,7 +480,7 @@ private function validateMethodParameterAnnotations( array $methodArguments, int $previousCommentOpenPtr, int $previousCommentClosePtr - ) : void { + ): void { $argumentCount = count($methodArguments); $paramCount = count($paramPointers); $this->validateParameterAnnotationForArgumentExists( @@ -510,8 +510,14 @@ private function validateMethodParameterAnnotations( $phpcsFile, $paramPointers ); + $this->validateFormattingConsistency( + $paramDefinitions, + $methodArguments, + $phpcsFile, + $paramPointers + ); + $tokens = $phpcsFile->getTokens(); for ($ptr = 0; $ptr < count($methodArguments); $ptr++) { - $tokens = $phpcsFile->getTokens(); if (isset($paramPointers[$ptr])) { $this->validateArgumentNameInParameterAnnotationExists( $stackPtr, @@ -520,7 +526,7 @@ private function validateMethodParameterAnnotations( $methodArguments, $paramDefinitions ); - $paramContent = $tokens[$paramPointers[$ptr]+2]['content']; + $paramContent = $tokens[$paramPointers[$ptr] + 2]['content']; $paramContentExplode = explode(' ', $paramContent); $this->validateParameterAnnotationFormatIsCorrect( $ptr, @@ -540,36 +546,40 @@ public function process(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $numTokens = count($tokens); - $previousCommentOpenPtr = $phpcsFile->findPrevious(T_DOC_COMMENT_OPEN_TAG, $stackPtr-1, 0); - $previousCommentClosePtr = $phpcsFile->findPrevious(T_DOC_COMMENT_CLOSE_TAG, $stackPtr-1, 0); + $previousCommentOpenPtr = $phpcsFile->findPrevious(T_DOC_COMMENT_OPEN_TAG, $stackPtr - 1, 0); + $previousCommentClosePtr = $phpcsFile->findPrevious(T_DOC_COMMENT_CLOSE_TAG, $stackPtr - 1, 0); if (!$this->validateCommentBlockExists($phpcsFile, $previousCommentClosePtr, $stackPtr)) { $phpcsFile->addError('Comment block is missing', $stackPtr, 'MethodArguments'); return; } - $openParenthesisPtr = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr+1, $numTokens); - $closedParenthesisPtr = $phpcsFile->findNext(T_CLOSE_PARENTHESIS, $stackPtr+1, $numTokens); + $openParenthesisPtr = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr + 1, $numTokens); + $closedParenthesisPtr = $phpcsFile->findNext(T_CLOSE_PARENTHESIS, $stackPtr + 1, $numTokens); $methodArguments = $this->getMethodArguments($phpcsFile, $openParenthesisPtr, $closedParenthesisPtr); $paramPointers = $paramDefinitions = []; for ($tempPtr = $previousCommentOpenPtr; $tempPtr < $previousCommentClosePtr; $tempPtr++) { if (strtolower($tokens[$tempPtr]['content']) === '@param') { $paramPointers[] = $tempPtr; - $paramAnnotationParts = explode(' ', $tokens[$tempPtr+2]['content']); + $content = preg_replace('/\s+/', ' ', $tokens[$tempPtr + 2]['content'], 2); + $paramAnnotationParts = explode(' ', $content, 3); if (count($paramAnnotationParts) === 1) { if ((preg_match('/^\$.*/', $paramAnnotationParts[0]))) { $paramDefinitions[] = [ 'type' => null, - 'paramName' => rtrim(ltrim($tokens[$tempPtr+2]['content'], '&'), ',') + 'paramName' => rtrim(ltrim($tokens[$tempPtr + 2]['content'], '&'), ','), + 'comment' => null ]; } else { $paramDefinitions[] = [ - 'type' => $tokens[$tempPtr+2]['content'], - 'paramName' => null + 'type' => $tokens[$tempPtr + 2]['content'], + 'paramName' => null, + 'comment' => null ]; } } else { $paramDefinitions[] = [ 'type' => $paramAnnotationParts[0], - 'paramName' => rtrim(ltrim($paramAnnotationParts[1], '&'), ',') + 'paramName' => rtrim(ltrim($paramAnnotationParts[1], '&'), ','), + 'comment' => $paramAnnotationParts[2] ?? null, ]; } } @@ -584,4 +594,80 @@ public function process(File $phpcsFile, $stackPtr) $previousCommentClosePtr ); } + + /** + * Validates function params format consistency. + * + * @param array $paramDefinitions + * @param array $methodArguments + * @param File $phpcsFile + * @param array $paramPointers + * + * @see https://devdocs.magento.com/guides/v2.3/coding-standards/docblock-standard-general.html#format-consistency + */ + private function validateFormattingConsistency( + array $paramDefinitions, + array $methodArguments, + File $phpcsFile, + array $paramPointers + ): void { + $argumentPositions = []; + $commentPositions = []; + $tokens = $phpcsFile->getTokens(); + for ($ptr = 0; $ptr < count($methodArguments); $ptr++) { + if (isset($paramPointers[$ptr])) { + $paramContent = $tokens[$paramPointers[$ptr] + 2]['content']; + $paramDefinition = $paramDefinitions[$ptr]; + $argumentPositions[] = strpos($paramContent, $paramDefinition['paramName']); + $commentPositions[] = $paramDefinition['comment'] + ? strpos($paramContent, $paramDefinition['comment']) : null; + } + } + if (!$this->allParamsAligned($argumentPositions, $commentPositions) + && !$this->noneParamsAligned($argumentPositions, $commentPositions, $paramDefinitions)) { + $phpcsFile->addFixableError( + 'Visual alignment must be consistent', + $paramPointers[0], + 'MethodArguments' + ); + } + } + + /** + * Check all params are aligned. + * + * @param array $argumentPositions + * @param array $commentPositions + * @return bool + */ + private function allParamsAligned(array $argumentPositions, array $commentPositions): bool + { + return count(array_unique($argumentPositions)) === 1 + && count(array_unique(array_filter($commentPositions))) <= 1; + } + + /** + * Check none of params are aligned. + * + * @param array $argumentPositions + * @param array $commentPositions + * @param array $paramDefinitions + * @return bool + */ + private function noneParamsAligned(array $argumentPositions, array $commentPositions, array $paramDefinitions): bool + { + $flag = true; + foreach ($argumentPositions as $index => $argumentPosition) { + $commentPosition = $commentPositions[$index]; + $type = $paramDefinitions[$index]['type']; + $paramName = $paramDefinitions[$index]['paramName']; + if (($argumentPosition !== strlen($type) + 1) || + (isset($commentPosition) && ($commentPosition !== $argumentPosition + strlen($paramName) + 1))) { + $flag = false; + break; + } + } + + return $flag; + } } From 8f0c2332e712c174cb8ff946553f87995d9bf4ea Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Sat, 13 Apr 2019 18:35:54 +0300 Subject: [PATCH 494/603] magento/graphql-ce#540: Replace deprecated fixture --- .../Ups/SetUpsShippingMethodsOnCartTest.php | 479 +++++++++++------- .../Quote/_files/set_new_shipping_address.php | 2 +- .../set_new_shipping_canada_address.php | 43 ++ 3 files changed, 349 insertions(+), 175 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/set_new_shipping_canada_address.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index de05a860f6b06..ccb9257701849 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -14,7 +14,37 @@ use Magento\TestFramework\TestCase\GraphQlAbstract; /** - * Test for setting "UPS" shipping method on cart + * Test for setting "UPS" shipping method on cart. Current class covers the next UPS shipping methods: + * + * | Code | Label + * -------------------------------------- + * | 1DM | Next Day Air Early AM + * | 1DA | Next Day Air + * | 2DA | 2nd Day Air + * | 3DS | 3 Day Select + * | GND | Ground + * | STD | Canada Standard + * | XPR | Worldwide Express + * | WXS | Worldwide Express Saver + * | XDM | Worldwide Express Plus + * | XPD | Worldwide Expedited + * + * Current class does not cover these UPS shipping methods (depends on sandbox settings) + * + * | Code | Label + * -------------------------------------- + * | 1DML | Next Day Air Early AM Letter + * | 1DAL | Next Day Air Letter + * | 1DAPI | Next Day Air Intra (Puerto Rico) + * | 1DP | Next Day Air Saver + * | 1DPL | Next Day Air Saver Letter + * | 2DM | 2nd Day Air AM + * | 2DML | 2nd Day Air AM Letter + * | 2DAL | 2nd Day Air Letter + * | GNDCOM | Ground Commercial + * | GNDRES | Ground Residential + * | XPRL | Worldwide Express Letter + * | XDML | Worldwide Express Plus Letter */ class SetUpsShippingMethodsOnCartTest extends GraphQlAbstract { @@ -55,24 +85,26 @@ protected function setUp() } /** + * Set "Next Day Air Early AM" UPS shipping method + * + * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php - * - * @param string $methodCode - * @param string $methodLabel - * @dataProvider availableForCartShippingMethods */ - public function testSetAvailableUpsShippingMethodOnCart(string $methodCode, string $methodLabel) + public function testSetNextDayAirEarlyAmUpsShippingMethod() { $quoteReservedId = 'test_quote'; + $methodCode = '1DM'; + $methodLabel = 'Next Day Air Early AM'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); - $response = $this->graphQlQuery($query); + $response = $this->sendRequestWithToken($query); self::assertArrayHasKey('setShippingMethodsOnCart', $response); self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); @@ -96,291 +128,390 @@ public function testSetAvailableUpsShippingMethodOnCart(string $methodCode, stri } /** - * Set "Next Day Air Early AM" UPS shipping method + * Set "Next Day Air" UPS shipping method * * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php */ - public function testSetNextDayAirEarlyAmUpsShippingMethod() + public function testSetNextDayAirUpsShippingMethod() { $quoteReservedId = 'test_quote'; - $carrierMethodCode = '1DM'; - $carrierMethodLabel = 'Next Day Air Early AM'; + $methodCode = '1DA'; + $methodLabel = 'Next Day Air'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - $query = $this->getQuery( - $maskedQuoteId, - $shippingAddressId, - self::CARRIER_CODE, - $carrierMethodCode - ); - + $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); $response = $this->sendRequestWithToken($query); - $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses']; - $expectedResult = [ - 'carrier_code' => self::CARRIER_CODE, - 'method_code' => $carrierMethodCode, - 'label' => self::CARRIER_LABEL . ' - ' . $carrierMethodLabel, - ]; - self::assertEquals($addressesInformation[0]['selected_shipping_method'], $expectedResult); + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + + $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('selected_shipping_method', $shippingAddress); + + self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); + + self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); + self::assertEquals( + self::CARRIER_LABEL . ' - ' . $methodLabel, + $shippingAddress['selected_shipping_method']['label'] + ); } /** - * Set "Next Day Air" UPS shipping method + * Set "2nd Day Air" UPS shipping method * * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php */ - public function testSetNextDayAirUpsShippingMethod() + public function testSet2ndDayAirUpsShippingMethod() { $quoteReservedId = 'test_quote'; - $carrierMethodCode = '1DA'; - $carrierMethodLabel = 'Next Day Air'; + $methodCode = '2DA'; + $methodLabel = '2nd Day Air'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - $query = $this->getQuery( - $maskedQuoteId, - $shippingAddressId, - self::CARRIER_CODE, - $carrierMethodCode - ); - + $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); $response = $this->sendRequestWithToken($query); - $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses']; - $expectedResult = [ - 'carrier_code' => self::CARRIER_CODE, - 'method_code' => $carrierMethodCode, - 'label' => self::CARRIER_LABEL . ' - ' . $carrierMethodLabel, - ]; - self::assertEquals($addressesInformation[0]['selected_shipping_method'], $expectedResult); + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + + $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('selected_shipping_method', $shippingAddress); + + self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); + + self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); + self::assertEquals( + self::CARRIER_LABEL . ' - ' . $methodLabel, + $shippingAddress['selected_shipping_method']['label'] + ); } /** - * Set "2nd Day Air" UPS shipping method + * Set "3 Day Select" UPS shipping method * * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php */ - public function testSet2ndDayAirUpsShippingMethod() + public function testSet3DaySelectUpsShippingMethod() { $quoteReservedId = 'test_quote'; - $carrierMethodCode = '2DA'; - $carrierMethodLabel = '2nd Day Air'; + $methodCode = '3DS'; + $methodLabel = '3 Day Select'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - $query = $this->getQuery( - $maskedQuoteId, - $shippingAddressId, - self::CARRIER_CODE, - $carrierMethodCode - ); - + $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); $response = $this->sendRequestWithToken($query); - $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses']; - $expectedResult = [ - 'carrier_code' => self::CARRIER_CODE, - 'method_code' => $carrierMethodCode, - 'label' => self::CARRIER_LABEL . ' - ' . $carrierMethodLabel, - ]; - self::assertEquals($addressesInformation[0]['selected_shipping_method'], $expectedResult); + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + + $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('selected_shipping_method', $shippingAddress); + + self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); + + self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); + self::assertEquals( + self::CARRIER_LABEL . ' - ' . $methodLabel, + $shippingAddress['selected_shipping_method']['label'] + ); } /** - * Set "3 Day Select" UPS shipping method + * Set "Ground" UPS shipping method * * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php */ - public function testSet3DaySelectUpsShippingMethod() + public function testSetGroundUpsShippingMethod() { $quoteReservedId = 'test_quote'; - $carrierMethodCode = '3DS'; - $carrierMethodLabel = '3 Day Select'; + $methodCode = 'GND'; + $methodLabel = 'Ground'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - $query = $this->getQuery( - $maskedQuoteId, - $shippingAddressId, - self::CARRIER_CODE, - $carrierMethodCode - ); - + $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); $response = $this->sendRequestWithToken($query); - $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses']; - $expectedResult = [ - 'carrier_code' => self::CARRIER_CODE, - 'method_code' => $carrierMethodCode, - 'label' => self::CARRIER_LABEL . ' - ' . $carrierMethodLabel, - ]; - self::assertEquals($addressesInformation[0]['selected_shipping_method'], $expectedResult); + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + + $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('selected_shipping_method', $shippingAddress); + + self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); + + self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); + self::assertEquals( + self::CARRIER_LABEL . ' - ' . $methodLabel, + $shippingAddress['selected_shipping_method']['label'] + ); } /** - * Set "Ground" UPS shipping method + * Set "Canada Standard" UPS shipping method * * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_canada_address.php + * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php */ - public function testSetGroundUpsShippingMethod() + public function testSetCanadaStandardUpsShippingMethod() { $quoteReservedId = 'test_quote'; - $carrierMethodCode = 'GND'; - $carrierMethodLabel = 'Ground'; + $methodCode = 'STD'; + $methodLabel = 'Canada Standard'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - $query = $this->getQuery( - $maskedQuoteId, - $shippingAddressId, - self::CARRIER_CODE, - $carrierMethodCode - ); - + $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); $response = $this->sendRequestWithToken($query); - $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses']; - $expectedResult = [ - 'carrier_code' => self::CARRIER_CODE, - 'method_code' => $carrierMethodCode, - 'label' => self::CARRIER_LABEL . ' - ' . $carrierMethodLabel, - ]; - self::assertEquals($addressesInformation[0]['selected_shipping_method'], $expectedResult); + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + + $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('selected_shipping_method', $shippingAddress); + + self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); + + self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); + self::assertEquals( + self::CARRIER_LABEL . ' - ' . $methodLabel, + $shippingAddress['selected_shipping_method']['label'] + ); } /** + * Set "Worldwide Express" UPS shipping method + * * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/Ups/_files/enable_ups_shipping_method.php - * - * @param string $carrierMethodCode - * @param string $carrierMethodLabel - * @dataProvider notAvailableForCartShippingMethods + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_canada_address.php + * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php */ - public function testSetNotAvailableForCartUpsShippingMethod(string $carrierMethodCode, string $carrierMethodLabel) + public function testSetWorldwideExpressUpsShippingMethod() { $quoteReservedId = 'test_quote'; + $methodCode = 'XPR'; + $methodLabel = 'Worldwide Express'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - $query = $this->getQuery( - $maskedQuoteId, - $shippingAddressId, - self::CARRIER_CODE, - $carrierMethodCode - ); + $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); + $response = $this->sendRequestWithToken($query); - $this->expectExceptionMessage( - "GraphQL response contains errors: Carrier with such method not found: " . self::CARRIER_CODE . ", " . $carrierMethodCode - ); + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - $response = $this->sendRequestWithToken($query); + $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('selected_shipping_method', $shippingAddress); + + self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); - $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses']; - $expectedResult = [ - 'carrier_code' => self::CARRIER_CODE, - 'method_code' => $carrierMethodCode, - 'label' => self::CARRIER_LABEL . ' - ' . $carrierMethodLabel, - ]; - self::assertEquals($addressesInformation[0]['selected_shipping_method'], $expectedResult); + self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); + self::assertEquals( + self::CARRIER_LABEL . ' - ' . $methodLabel, + $shippingAddress['selected_shipping_method']['label'] + ); } /** - * @return array + * Set "Worldwide Express Saver" UPS shipping method + * + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_canada_address.php + * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php */ - public function availableForCartShippingMethods(): array + public function testSetWorldwideExpressSaverUpsShippingMethod() { - $shippingMethods = ['1DM', '1DA', '2DA', '3DS', 'GND']; + $quoteReservedId = 'test_quote'; + $methodCode = 'WXS'; + $methodLabel = 'Worldwide Express Saver'; + + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); + $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); + + $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); + $response = $this->sendRequestWithToken($query); + + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + + $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('selected_shipping_method', $shippingAddress); - return $this->filterShippingMethodsByCodes($shippingMethods); + self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); + + self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); + self::assertEquals( + self::CARRIER_LABEL . ' - ' . $methodLabel, + $shippingAddress['selected_shipping_method']['label'] + ); } /** - * @return array + * Set "Worldwide Express Plus" UPS shipping method + * + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_canada_address.php + * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php */ - public function notAvailableForCartShippingMethods(): array + public function testSetWorldwideExpressPlusUpsShippingMethod() { - $shippingMethods = ['1DML', '1DAL', '1DAPI', '1DP', '1DPL', '2DM', '2DML', '2DAL', 'GNDCOM', 'GNDRES', 'STD', 'XPR', 'WXS', 'XPRL', 'XDM', 'XDML', 'XPD']; + $quoteReservedId = 'test_quote'; + $methodCode = 'XDM'; + $methodLabel = 'Worldwide Express Plus'; + + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); + $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); + + $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); + $response = $this->sendRequestWithToken($query); + + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - return $this->filterShippingMethodsByCodes($shippingMethods); + $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('selected_shipping_method', $shippingAddress); + + self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); + + self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); + self::assertEquals( + self::CARRIER_LABEL . ' - ' . $methodLabel, + $shippingAddress['selected_shipping_method']['label'] + ); } /** - * @param array $filter - * @return array + * Set "Worldwide Expedited" UPS shipping method + * + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_canada_address.php + * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php */ - private function filterShippingMethodsByCodes(array $filter):array + public function testSetWorldwideExpeditedUpsShippingMethod() { - $result = []; - foreach ($this->getAllUpsShippingMethods() as $shippingMethod) { - if (in_array($shippingMethod[0], $filter)) { - $result[] = $shippingMethod; - } - } - return $result; - } + $quoteReservedId = 'test_quote'; + $methodCode = 'XPD'; + $methodLabel = 'Worldwide Expedited'; - private function getAllUpsShippingMethods():array - { - return [ - ['1DM', 'Next Day Air Early AM'], // - ['1DML', 'Next Day Air Early AM Letter'], - ['1DA', 'Next Day Air'], // - ['1DAL', 'Next Day Air Letter'], - ['1DAPI', 'Next Day Air Intra (Puerto Rico)'], - ['1DP', 'Next Day Air Saver'], - ['1DPL', 'Next Day Air Saver Letter'], - ['2DM', '2nd Day Air AM'], - ['2DML', '2nd Day Air AM Letter'], - ['2DA', '2nd Day Air'], // - ['2DAL', '2nd Day Air Letter'], - ['3DS', '3 Day Select'], // - ['GND', 'Ground'], // - ['GNDCOM', 'Ground Commercial'], - ['GNDRES', 'Ground Residential'], - ['STD', 'Canada Standard'], - ['XPR', 'Worldwide Express'], - ['WXS', 'Worldwide Express Saver'], - ['XPRL', 'Worldwide Express Letter'], - ['XDM', 'Worldwide Express Plus'], - ['XDML', 'Worldwide Express Plus Letter'], - ['XPD', 'Worldwide Expedited'], - ]; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); + $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); + + $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); + $response = $this->sendRequestWithToken($query); + + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + + $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('selected_shipping_method', $shippingAddress); + + self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); + + self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); + self::assertEquals( + self::CARRIER_LABEL . ' - ' . $methodLabel, + $shippingAddress['selected_shipping_method']['label'] + ); } /** diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/set_new_shipping_address.php b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/set_new_shipping_address.php index e17b9e61f82db..54f4d8d0c6e75 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/set_new_shipping_address.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/set_new_shipping_address.php @@ -26,7 +26,7 @@ $quoteAddressData = [ AddressInterface::KEY_TELEPHONE => 3468676, - AddressInterface::KEY_POSTCODE => 75477, + AddressInterface::KEY_POSTCODE => '75477', AddressInterface::KEY_COUNTRY_ID => 'US', AddressInterface::KEY_CITY => 'CityM', AddressInterface::KEY_COMPANY => 'CompanyName', diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/set_new_shipping_canada_address.php b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/set_new_shipping_canada_address.php new file mode 100644 index 0000000000000..8e60dc904bd4e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/set_new_shipping_canada_address.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\Api\DataObjectHelper; +use Magento\Quote\Api\Data\AddressInterface; +use Magento\Quote\Api\Data\AddressInterfaceFactory; +use Magento\Quote\Model\QuoteFactory; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\Quote\Model\ShippingAddressManagementInterface; +use Magento\TestFramework\Helper\Bootstrap; + +/** @var QuoteFactory $quoteFactory */ +$quoteFactory = Bootstrap::getObjectManager()->get(QuoteFactory::class); +/** @var QuoteResource $quoteResource */ +$quoteResource = Bootstrap::getObjectManager()->get(QuoteResource::class); +/** @var AddressInterfaceFactory $quoteAddressFactory */ +$quoteAddressFactory = Bootstrap::getObjectManager()->get(AddressInterfaceFactory::class); +/** @var DataObjectHelper $dataObjectHelper */ +$dataObjectHelper = Bootstrap::getObjectManager()->get(DataObjectHelper::class); +/** @var ShippingAddressManagementInterface $shippingAddressManagement */ +$shippingAddressManagement = Bootstrap::getObjectManager()->get(ShippingAddressManagementInterface::class); + +$quoteAddressData = [ + AddressInterface::KEY_TELEPHONE => 3468676, + AddressInterface::KEY_POSTCODE => 'M4L 1V3', + AddressInterface::KEY_COUNTRY_ID => 'CA', + AddressInterface::KEY_CITY => 'Toronto', + AddressInterface::KEY_COMPANY => 'CompanyName', + AddressInterface::KEY_STREET => '500 Kingston Rd', + AddressInterface::KEY_LASTNAME => 'Smith', + AddressInterface::KEY_FIRSTNAME => 'John', + AddressInterface::KEY_REGION_CODE => 'ON', +]; +$quoteAddress = $quoteAddressFactory->create(); +$dataObjectHelper->populateWithArray($quoteAddress, $quoteAddressData, AddressInterfaceFactory::class); + +$quote = $quoteFactory->create(); +$quoteResource->load($quote, 'test_quote', 'reserved_order_id'); +$shippingAddressManagement->assign($quote->getId(), $quoteAddress); From 9d475b828a323d072619c3332fb3408ead9d7ca5 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Sat, 13 Apr 2019 18:49:38 +0300 Subject: [PATCH 495/603] magento/graphql-ce#540: Replace deprecated fixture 1. Use POST for mutation query instead of GET --- .../Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index ccb9257701849..b41c7d0898f79 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -567,6 +567,6 @@ private function sendRequestWithToken(string $query): array $customerToken = $this->customerTokenService->createCustomerAccessToken('customer@example.com', 'password'); $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; - return $this->graphQlQuery($query, [], '', $headerMap); + return $this->graphQlMutation($query, [], '', $headerMap); } } From 12c848c79237bb4e6237e4ac4dd5d989ec9bbc53 Mon Sep 17 00:00:00 2001 From: Pieter Hoste <hoste.pieter@gmail.com> Date: Sun, 14 Apr 2019 19:45:14 +0200 Subject: [PATCH 496/603] Fixes a less compilation error: '.no-link a' isn't defined when .email-non-inline() isn't active, so when using '.no-link a', it should be wrapped inside .email-non-inline(). --- .../Magento/blank/Magento_Sales/web/css/source/_email.less | 6 ++++-- .../Magento/luma/Magento_Sales/web/css/source/_email.less | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_email.less b/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_email.less index 215d7d8b322b4..b189d4e08ba17 100644 --- a/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_email.less +++ b/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_email.less @@ -68,8 +68,10 @@ } // Remove address and phone number link color on iOS -.address-details a { - &:extend(.no-link a); +.email-non-inline() { + .address-details a { + &:extend(.no-link a); + } } .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xs) { diff --git a/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_email.less b/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_email.less index 3f19d1020bab9..31c128e07e3a6 100644 --- a/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_email.less +++ b/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_email.less @@ -76,8 +76,10 @@ } // Remove address and phone number link color on iOS -.address-details a { - &:extend(.no-link a); +.email-non-inline() { + .address-details a { + &:extend(.no-link a); + } } .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xs) { From 87ae19b8b9505de542ef87a8ff960d26d8efdaf1 Mon Sep 17 00:00:00 2001 From: Stas Puga <stas.puga@transoftgroup.com> Date: Mon, 15 Apr 2019 08:56:45 +0300 Subject: [PATCH 497/603] MC-11944: Create Order from Admin within Offline Payment Methods --- .../Sales/Test/TestCase/CreateOrderBackendPartOneTest.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderBackendPartOneTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderBackendPartOneTest.xml index 3e7b8fad1f04d..880c66483d5f2 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderBackendPartOneTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderBackendPartOneTest.xml @@ -8,7 +8,6 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Sales\Test\TestCase\CreateOrderBackendPartOneTest" summary="Create Order from Admin within Offline Payment Methods" ticketId="MAGETWO-28696"> <variation name="CreateOrderBackendTestVariation1" ticketId="MAGETWO-17063"> - <data name="issue" xsi:type="string">https://github.com/magento-engcom/msi/issues/1624</data> <data name="description" xsi:type="string">Create order with simple product for registered US customer using Fixed shipping method and Cash on Delivery payment method</data> <data name="products/0" xsi:type="string">catalogProductSimple::with_one_custom_option</data> <data name="customer/dataset" xsi:type="string">default</data> @@ -70,7 +69,6 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderByDateInOrdersGrid" /> </variation> <variation name="CreateOrderBackendTestVariation4"> - <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="description" xsi:type="string">Create order with virtual product for registered UK customer using Bank Transfer payment method</data> <data name="products/0" xsi:type="string">catalogProductVirtual::default</data> <data name="customer/dataset" xsi:type="string">default</data> From 9d592efec6cb0045b22a591009895f20c2e165a9 Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Mon, 15 Apr 2019 10:09:48 +0300 Subject: [PATCH 498/603] MC-5264: Create root category with all fields --- .../Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml index ea6808ee2a7f5..663439fd62a1d 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml @@ -17,7 +17,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForm" /> </variation> <variation name="CreateCategoryEntityTestVariation2_RootCategory_AllFields"> - <data name="issue" xsi:type="string">MAGETWO-60635: [CE][Categories] Design update dates are incorrect after save</data> <data name="description" xsi:type="string">Create root category with all fields</data> <data name="addCategory" xsi:type="string">addRootCategory</data> <data name="category/data/is_active" xsi:type="string">Yes</data> @@ -58,7 +57,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryPage" /> </variation> <variation name="CreateCategoryEntityTestVariation4_Subcategory_AllFields"> - <data name="issue" xsi:type="string">MAGETWO-60635: [CE][Categories] Design update dates are incorrect after save</data> <data name="description" xsi:type="string">Create not anchor subcategory specifying all fields</data> <data name="addCategory" xsi:type="string">addSubcategory</data> <data name="category/data/parent_id/dataset" xsi:type="string">default_category</data> From 6cbf55d40ebb33e5fb73c68ba62df83f2af98aa2 Mon Sep 17 00:00:00 2001 From: niravkrish <nirav.patel@krishtechnolabs.com> Date: Mon, 15 Apr 2019 14:20:41 +0530 Subject: [PATCH 499/603] Fixed - search icon click not working issue in admin ui grid sticky header --- .../Ui/view/base/web/js/grid/search/search.js | 23 +++++++++++++++---- .../web/templates/grid/search/search.html | 3 ++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/grid/search/search.js b/app/code/Magento/Ui/view/base/web/js/grid/search/search.js index 999e3262dbbdd..ce53b23b79e11 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/search/search.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/search/search.js @@ -11,8 +11,9 @@ define([ 'uiLayout', 'mage/translate', 'mageUtils', - 'uiElement' -], function (_, layout, $t, utils, Element) { + 'uiElement', + 'jquery' +], function (_, layout, $t, utils, Element, $) { 'use strict'; return Element.extend({ @@ -29,11 +30,13 @@ define([ tracks: { value: true, previews: true, - inputValue: true + inputValue: true, + focused: true }, imports: { inputValue: 'value', - updatePreview: 'value' + updatePreview: 'value', + focused: false }, exports: { value: '${ $.provider }:params.search' @@ -88,6 +91,18 @@ define([ return this; }, + /** + * Click To ScrollTop. + */ + scrollTo: function ($data) { + $('html, body').animate({ + scrollTop: 0 + }, 'slow', function () { + $data.focused = false; + $data.focused = true; + }); + }, + /** * Resets input value to the last applied state. * diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/search/search.html b/app/code/Magento/Ui/view/base/web/templates/grid/search/search.html index 13b82a93eca25..fcad729a95fbb 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/search/search.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/search/search.html @@ -5,7 +5,7 @@ */ --> <div class="data-grid-search-control-wrap"> - <label class="data-grid-search-label" attr="title: $t('Search'), for: index"> + <label class="data-grid-search-label" attr="title: $t('Search'), for: index" data-bind="click: scrollTo"> <span translate="'Search'"/> </label> <input class="admin__control-text data-grid-search-control" type="text" @@ -16,6 +16,7 @@ placeholder: $t(placeholder) }, textInput: inputValue, + hasFocus: focused, keyboard: { 13: apply.bind($data, false), 27: cancel From ef5d0013c487b992eb93b41b0e8f2abee8917e81 Mon Sep 17 00:00:00 2001 From: Sudhanshu Bajaj <sudhanshu.b@lsretail.com> Date: Mon, 15 Apr 2019 16:52:23 +0800 Subject: [PATCH 500/603] Spelling Mistake in Setup > Patch --- .../Magento/Framework/Setup/Patch/DependentPatchInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php b/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php index abda94a0e6f8e..21fafd273f9ed 100644 --- a/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php +++ b/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php @@ -6,7 +6,7 @@ namespace Magento\Framework\Setup\Patch; /** - * Each patch can have dependecies, that should be applied before such patch + * Each patch can have dependencies, that should be applied before such patch * * / Patch2 --- Patch3 * / From d334e2e6808dd5d6e616dc34894710b02861a6f5 Mon Sep 17 00:00:00 2001 From: Shikha Mishra <shikhamishra@cedcoss.com> Date: Mon, 15 Apr 2019 14:44:38 +0530 Subject: [PATCH 501/603] Fixed Value of created_at and updated_at columns --- app/code/Magento/Ui/etc/db_schema.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ui/etc/db_schema.xml b/app/code/Magento/Ui/etc/db_schema.xml index e2a04b0cdc72d..13a384024f18a 100644 --- a/app/code/Magento/Ui/etc/db_schema.xml +++ b/app/code/Magento/Ui/etc/db_schema.xml @@ -18,8 +18,8 @@ comment="Mark current bookmark per user and identifier"/> <column xsi:type="varchar" name="title" nullable="true" length="255" comment="Bookmark title"/> <column xsi:type="longtext" name="config" nullable="true" comment="Bookmark config"/> - <column xsi:type="datetime" name="created_at" on_update="false" nullable="false" comment="Bookmark created at"/> - <column xsi:type="datetime" name="updated_at" on_update="false" nullable="false" comment="Bookmark updated at"/> + <column xsi:type="datetime" name="created_at" on_update="false" nullable="false" default="CURRENT_TIMESTAMP" comment="Bookmark created at"/> + <column xsi:type="datetime" name="updated_at" on_update="true" nullable="false" default="CURRENT_TIMESTAMP" comment="Bookmark updated at"/> <constraint xsi:type="primary" referenceId="PRIMARY"> <column name="bookmark_id"/> </constraint> From a45fb74cac0e9efa8a5ce9c304a8b55f1ce6e393 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Mon, 15 Apr 2019 16:40:34 +0300 Subject: [PATCH 502/603] magento/magento2#21797: Static test fix. --- .../testsuite/Magento/Webapi/JoinDirectivesTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php index d00cfb831953e..8beb14e81be71 100644 --- a/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php @@ -11,6 +11,9 @@ use Magento\Framework\Api\SortOrder; use Magento\Framework\Api\SortOrderBuilder; +/** + * Test join directives. + */ class JoinDirectivesTest extends \Magento\TestFramework\TestCase\WebapiAbstract { /** @@ -43,7 +46,8 @@ protected function setUp() } /** - * Rollback rules + * Rollback rules. + * * @magentoApiDataFixture Magento/SalesRule/_files/rules_rollback.php * @magentoApiDataFixture Magento/Sales/_files/quote.php */ From fecce53f4cc2ba2edb6f227c271be49ce179e753 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Mon, 15 Apr 2019 11:24:04 -0500 Subject: [PATCH 503/603] Fix for issue #21299. Change HEAD action mapping to GET action interface and add HEAD request handling --- .../Framework/App/Test/Unit/HttpTest.php | 117 ++++++++++++------ .../Test/Unit/Transfer/Adapter/HttpTest.php | 28 +++-- .../Framework/File/Transfer/Adapter/Http.php | 2 +- 3 files changed, 94 insertions(+), 53 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php index 48a1242a90d4f..23e58bd3df1e8 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php @@ -135,12 +135,17 @@ private function setUpLaunch() { $frontName = 'frontName'; $areaCode = 'areaCode'; - $this->requestMock->expects($this->once())->method('getFrontName')->will($this->returnValue($frontName)); + $this->requestMock->expects($this->once()) + ->method('getFrontName') + ->willReturn($frontName); $this->areaListMock->expects($this->once()) ->method('getCodeByFrontName') - ->with($frontName)->will($this->returnValue($areaCode)); + ->with($frontName) + ->willReturn($areaCode); $this->configLoaderMock->expects($this->once()) - ->method('load')->with($areaCode)->will($this->returnValue([])); + ->method('load') + ->with($areaCode) + ->willReturn([]); $this->objectManagerMock->expects($this->once())->method('configure')->with([]); $this->objectManagerMock->expects($this->once()) ->method('get') @@ -149,13 +154,15 @@ private function setUpLaunch() $this->frontControllerMock->expects($this->once()) ->method('dispatch') ->with($this->requestMock) - ->will($this->returnValue($this->responseMock)); + ->willReturn($this->responseMock); } public function testLaunchSuccess() { $this->setUpLaunch(); - $this->requestMock->expects($this->once())->method('isHead')->will($this->returnValue(false)); + $this->requestMock->expects($this->once()) + ->method('isHead') + ->willReturn(false); $this->eventManagerMock->expects($this->once()) ->method('dispatch') ->with( @@ -172,14 +179,16 @@ public function testLaunchSuccess() public function testLaunchException() { $this->setUpLaunch(); - $this->frontControllerMock->expects($this->once())->method('dispatch')->with($this->requestMock)->will( - $this->returnCallback( - function () { - // phpcs:ignore Magento2.Exceptions.DirectThrow - throw new \Exception('Message'); - } - ) - ); + $this->frontControllerMock->expects($this->once()) + ->method('dispatch') + ->with($this->requestMock)->will( + $this->returnCallback( + function () { + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \Exception('Message'); + } + ) + ); $this->http->launch(); } @@ -192,20 +201,22 @@ function () { public function testLaunchHeadRequest($body, $expectedLength) { $this->setUpLaunch(); - $this->requestMock->expects($this->once())->method('isHead')->will($this->returnValue(true)); + $this->requestMock->expects($this->once()) + ->method('isHead') + ->willReturn(true); $this->responseMock->expects($this->once()) ->method('getHttpResponseCode') - ->will($this->returnValue(200)); + ->willReturn(200); $this->responseMock->expects($this->once()) ->method('getContent') - ->will($this->returnValue($body)); + ->willReturn($body); $this->responseMock->expects($this->once()) ->method('clearBody') - ->will($this->returnValue($this->responseMock)); + ->willReturn($this->responseMock); $this->responseMock->expects($this->once()) ->method('setHeader') ->with('Content-Length', $expectedLength) - ->will($this->returnValue($this->responseMock)); + ->willReturn($this->responseMock); $this->eventManagerMock->expects($this->once()) ->method('dispatch') ->with( @@ -219,7 +230,7 @@ public function testLaunchHeadRequest($body, $expectedLength) * Different test content for responseMock with their expected lengths in bytes. * @return array */ - public function dataProviderForTestLaunchHeadRequest() + public function dataProviderForTestLaunchHeadRequest(): array { return [ [ @@ -244,20 +255,29 @@ public function dataProviderForTestLaunchHeadRequest() public function testHandleDeveloperModeNotInstalled() { $dir = $this->getMockForAbstractClass(\Magento\Framework\Filesystem\Directory\ReadInterface::class); - $dir->expects($this->once())->method('getAbsolutePath')->willReturn(__DIR__); + $dir->expects($this->once()) + ->method('getAbsolutePath') + ->willReturn(__DIR__); $this->filesystemMock->expects($this->once()) ->method('getDirectoryRead') ->with(DirectoryList::ROOT) ->willReturn($dir); - $this->responseMock->expects($this->once())->method('setRedirect')->with('/_files/'); - $this->responseMock->expects($this->once())->method('sendHeaders'); + $this->responseMock->expects($this->once()) + ->method('setRedirect') + ->with('/_files/'); + $this->responseMock->expects($this->once()) + ->method('sendHeaders'); $bootstrap = $this->getBootstrapNotInstalled(); - $bootstrap->expects($this->once())->method('getParams')->willReturn([ - 'SCRIPT_NAME' => '/index.php', - 'DOCUMENT_ROOT' => __DIR__, - 'SCRIPT_FILENAME' => __DIR__ . '/index.php', - SetupInfo::PARAM_NOT_INSTALLED_URL_PATH => '_files', - ]); + $bootstrap->expects($this->once()) + ->method('getParams') + ->willReturn( + [ + 'SCRIPT_NAME' => '/index.php', + 'DOCUMENT_ROOT' => __DIR__, + 'SCRIPT_FILENAME' => __DIR__ . '/index.php', + SetupInfo::PARAM_NOT_INSTALLED_URL_PATH => '_files', + ] + ); $this->assertTrue($this->http->catchException($bootstrap, new \Exception('Test Message'))); } @@ -266,24 +286,37 @@ public function testHandleDeveloperMode() $this->filesystemMock->expects($this->once()) ->method('getDirectoryRead') ->will($this->throwException(new \Exception('strange error'))); - $this->responseMock->expects($this->once())->method('setHttpResponseCode')->with(500); - $this->responseMock->expects($this->once())->method('setHeader')->with('Content-Type', 'text/plain'); + $this->responseMock->expects($this->once()) + ->method('setHttpResponseCode') + ->with(500); + $this->responseMock->expects($this->once()) + ->method('setHeader') + ->with('Content-Type', 'text/plain'); $constraint = new \PHPUnit\Framework\Constraint\StringStartsWith('1 exception(s):'); - $this->responseMock->expects($this->once())->method('setBody')->with($constraint); - $this->responseMock->expects($this->once())->method('sendResponse'); + $this->responseMock->expects($this->once()) + ->method('setBody') + ->with($constraint); + $this->responseMock->expects($this->once()) + ->method('sendResponse'); $bootstrap = $this->getBootstrapNotInstalled(); - $bootstrap->expects($this->once())->method('getParams')->willReturn( - ['DOCUMENT_ROOT' => 'something', 'SCRIPT_FILENAME' => 'something/else'] - ); + $bootstrap->expects($this->once()) + ->method('getParams') + ->willReturn( + ['DOCUMENT_ROOT' => 'something', 'SCRIPT_FILENAME' => 'something/else'] + ); $this->assertTrue($this->http->catchException($bootstrap, new \Exception('Test'))); } public function testCatchExceptionSessionException() { - $this->responseMock->expects($this->once())->method('setRedirect'); - $this->responseMock->expects($this->once())->method('sendHeaders'); + $this->responseMock->expects($this->once()) + ->method('setRedirect'); + $this->responseMock->expects($this->once()) + ->method('sendHeaders'); $bootstrap = $this->createMock(\Magento\Framework\App\Bootstrap::class); - $bootstrap->expects($this->once())->method('isDeveloperMode')->willReturn(false); + $bootstrap->expects($this->once()) + ->method('isDeveloperMode') + ->willReturn(false); $this->assertTrue($this->http->catchException( $bootstrap, new \Magento\Framework\Exception\SessionException(new \Magento\Framework\Phrase('Test')) @@ -298,8 +331,12 @@ public function testCatchExceptionSessionException() private function getBootstrapNotInstalled() { $bootstrap = $this->createMock(\Magento\Framework\App\Bootstrap::class); - $bootstrap->expects($this->once())->method('isDeveloperMode')->willReturn(true); - $bootstrap->expects($this->once())->method('getErrorCode')->willReturn(Bootstrap::ERR_IS_INSTALLED); + $bootstrap->expects($this->once()) + ->method('isDeveloperMode') + ->willReturn(true); + $bootstrap->expects($this->once()) + ->method('getErrorCode') + ->willReturn(Bootstrap::ERR_IS_INSTALLED); return $bootstrap; } } diff --git a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php index 92db004ae8e8e..8147ed4eb0005 100644 --- a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php +++ b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php @@ -6,7 +6,11 @@ namespace Magento\Framework\File\Test\Unit\Transfer\Adapter; -use \Magento\Framework\File\Transfer\Adapter\Http; +use Magento\Framework\File\Transfer\Adapter\Http; +use Magento\Framework\File\Mime; +use Magento\Framework\HTTP\PhpEnvironment\Response; +use Magento\Framework\App\Request\Http as RequestHttp; +use PHPUnit\Framework\MockObject\MockObject; /** * Tests http transfer adapter. @@ -14,22 +18,22 @@ class HttpTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject + * @var RequestHttp|MockObject */ private $request; /** - * @var \Magento\Framework\HTTP\PhpEnvironment\Response|\PHPUnit_Framework_MockObject_MockObject + * @var Response|MockObject */ private $response; /** - * @var Http|\PHPUnit_Framework_MockObject_MockObject + * @var Http|MockObject */ private $object; /** - * @var \Magento\Framework\File\Mime|\PHPUnit_Framework_MockObject_MockObject + * @var Mime|MockObject */ private $mime; @@ -39,12 +43,12 @@ class HttpTest extends \PHPUnit\Framework\TestCase protected function setUp() { $this->response = $this->createPartialMock( - \Magento\Framework\HTTP\PhpEnvironment\Response::class, + Response::class, ['setHeader', 'sendHeaders', 'setHeaders'] ); - $this->mime = $this->createMock(\Magento\Framework\File\Mime::class); + $this->mime = $this->createMock(Mime::class); $this->request = $this->createPartialMock( - \Magento\Framework\App\Request\Http::class, + RequestHttp::class, ['isHead'] ); $this->object = new Http($this->response, $this->mime, $this->request); @@ -98,10 +102,10 @@ public function testSendWithOptions(): void $this->mime->expects($this->once()) ->method('getMimeType') ->with($file) - ->will($this->returnValue($contentType)); + ->willReturn($contentType); $this->request->expects($this->once()) ->method('isHead') - ->will($this->returnValue(false)); + ->willReturn(false); $this->expectOutputString(file_get_contents($file)); $this->object->send(['filepath' => $file, 'headers' => $headers]); @@ -145,10 +149,10 @@ public function testSendHeadRequest(): void $this->mime->expects($this->once()) ->method('getMimeType') ->with($file) - ->will($this->returnValue($contentType)); + ->willReturn($contentType); $this->request->expects($this->once()) ->method('isHead') - ->will($this->returnValue(true)); + ->willReturn(true); $this->object->send($file); $this->assertEquals(false, $this->hasOutput()); diff --git a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php index 7cafb826f766d..8c09fbdc45124 100644 --- a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php +++ b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php @@ -106,7 +106,7 @@ private function getFilePath($options): string * @param array $options * @param string $filepath */ - protected function prepareResponse($options, string $filepath): void + private function prepareResponse($options, string $filepath): void { $mimeType = $this->mime->getMimeType($filepath); if (is_array($options) && isset($options['headers']) && $options['headers'] instanceof \Zend\Http\Headers) { From 265d82e51adadf3d1c8ede0166c0aa82eac856f6 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 15 Apr 2019 12:31:55 -0500 Subject: [PATCH 504/603] GraphQL-425: [Place order] Cart grand total --- .../Resolver/{Totals.php => CartPrices.php} | 7 +- .../Magento/QuoteGraphQl/etc/schema.graphqls | 2 +- .../GraphQl/Quote/Customer/CartTotalsTest.php | 112 ++++++++++-------- .../GraphQl/Quote/Guest/CartTotalsTest.php | 69 ++++++----- 4 files changed, 102 insertions(+), 88 deletions(-) rename app/code/Magento/QuoteGraphQl/Model/Resolver/{Totals.php => CartPrices.php} (94%) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/Totals.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php similarity index 94% rename from app/code/Magento/QuoteGraphQl/Model/Resolver/Totals.php rename to app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php index 926f2b2de3cf2..7a9bdd926764c 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/Totals.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php @@ -11,13 +11,14 @@ use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; +use Magento\Quote\Model\Quote; use Magento\Quote\Model\Quote\Address\Total; use Magento\Quote\Model\Quote\TotalsCollector; /** * @inheritdoc */ -class Totals implements ResolverInterface +class CartPrices implements ResolverInterface { /** * @var TotalsCollector @@ -68,10 +69,11 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value */ private function getAppliedTaxes(Total $total, string $currency): array { + $appliedTaxesData = []; $appliedTaxes = $total->getAppliedTaxes(); if (count($appliedTaxes) === 0) { - return []; + return $appliedTaxesData; } foreach ($appliedTaxes as $appliedTax) { @@ -80,7 +82,6 @@ private function getAppliedTaxes(Total $total, string $currency): array 'amount' => ['value' => $appliedTax['amount'], 'currency' => $currency] ]; } - return $appliedTaxesData; } } diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 85a0703a137e5..70690b1023062 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -173,7 +173,7 @@ type Cart { billing_address: CartAddress! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\BillingAddress") available_payment_methods: [AvailablePaymentMethod] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AvailablePaymentMethods") @doc(description: "Available payment methods") selected_payment_method: SelectedPaymentMethod @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SelectedPaymentMethod") - prices: CartPrices @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\Totals") + prices: CartPrices @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartPrices") } type CartAddress { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php index 4a25e9331d86e..bb8acfce629ff 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php @@ -7,10 +7,8 @@ namespace Magento\GraphQl\Quote\Customer; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\Integration\Api\CustomerTokenServiceInterface; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -25,26 +23,14 @@ class CartTotalsTest extends GraphQlAbstract private $customerTokenService; /** - * @var QuoteResource + * @var GetMaskedQuoteIdByReservedOrderId */ - private $quoteResource; - - /** - * @var QuoteFactory - */ - private $quoteFactory; - - /** - * @var QuoteIdToMaskedQuoteIdInterface - */ - private $quoteIdToMaskedId; + private $getMaskedQuoteIdByReservedOrderId; protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); } @@ -60,9 +46,9 @@ protected function setUp() */ public function testGetCartTotalsWithTaxApplied() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_quote'); - $query = $this->getCartTotalsGraphqlQuery($maskedQuoteId); - $response = $this->sendRequestWithToken($query); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('prices', $response['cart']); $pricesResponse = $response['cart']['prices']; @@ -88,9 +74,9 @@ public function testGetCartTotalsWithTaxApplied() */ public function testGetTotalsWithNoTaxApplied() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_quote'); - $query = $this->getCartTotalsGraphqlQuery($maskedQuoteId); - $response = $this->sendRequestWithToken($query); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); $pricesResponse = $response['cart']['prices']; self::assertEquals(20, $pricesResponse['grand_total']['value']); @@ -111,9 +97,9 @@ public function testGetTotalsWithNoTaxApplied() */ public function testGetCartTotalsWithNoAddressSet() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_quote'); - $query = $this->getCartTotalsGraphqlQuery($maskedQuoteId); - $response = $this->sendRequestWithToken($query); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); $pricesResponse = $response['cart']['prices']; self::assertEquals(20, $pricesResponse['grand_total']['value']); @@ -123,13 +109,57 @@ public function testGetCartTotalsWithNoAddressSet() self::assertEmpty($pricesResponse['applied_taxes']); } + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + */ + public function testGetTotalsFromGuestCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + */ + public function testGetTotalsFromAnotherCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer3@search.example.com')); + } + /** * Generates GraphQl query for retrieving cart totals * * @param string $maskedQuoteId * @return string */ - private function getCartTotalsGraphqlQuery(string $maskedQuoteId): string + private function getQuery(string $maskedQuoteId): string { return <<<QUERY { @@ -165,30 +195,14 @@ private function getCartTotalsGraphqlQuery(string $maskedQuoteId): string } /** - * @param string $reversedQuoteId - * @return string - */ - private function getMaskedQuoteIdByReversedQuoteId(string $reversedQuoteId): string - { - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id'); - - return $this->quoteIdToMaskedId->execute((int)$quote->getId()); - } - - /** - * Sends a GraphQL request with using a bearer token - * - * @param string $query + * @param string $username + * @param string $password * @return array - * @throws \Magento\Framework\Exception\AuthenticationException */ - private function sendRequestWithToken(string $query): array + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array { - - $customerToken = $this->customerTokenService->createCustomerAccessToken('customer@example.com', 'password'); + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; - - return $this->graphQlQuery($query, [], '', $headerMap); + return $headerMap; } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php index 9fec6fdfd2697..ee2d6a2b31de0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php @@ -7,9 +7,7 @@ namespace Magento\GraphQl\Quote\Guest; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -19,26 +17,17 @@ class CartTotalsTest extends GraphQlAbstract { /** - * @var QuoteResource + * @var GetMaskedQuoteIdByReservedOrderId */ - private $quoteResource; + private $getMaskedQuoteIdByReservedOrderId; /** - * @var QuoteFactory + * @inheritdoc */ - private $quoteFactory; - - /** - * @var QuoteIdToMaskedQuoteIdInterface - */ - private $quoteIdToMaskedId; - protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); } /** @@ -52,8 +41,8 @@ protected function setUp() */ public function testGetCartTotalsWithTaxApplied() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_quote'); - $query = $this->getCartTotalsGraphqlQuery($maskedQuoteId); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); $response = $this->graphQlQuery($query); self::assertArrayHasKey('prices', $response['cart']); @@ -79,8 +68,8 @@ public function testGetCartTotalsWithTaxApplied() */ public function testGetTotalsWithNoTaxApplied() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_quote'); - $query = $this->getCartTotalsGraphqlQuery($maskedQuoteId); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); $response = $this->graphQlQuery($query); $pricesResponse = $response['cart']['prices']; @@ -102,8 +91,8 @@ public function testGetTotalsWithNoTaxApplied() */ public function testGetCartTotalsWithNoAddressSet() { - $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_quote'); - $query = $this->getCartTotalsGraphqlQuery($maskedQuoteId); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); $response = $this->graphQlQuery($query); $pricesResponse = $response['cart']['prices']; @@ -114,13 +103,35 @@ public function testGetCartTotalsWithNoAddressSet() self::assertEmpty($pricesResponse['applied_taxes']); } + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + */ + public function testGetSelectedShippingMethodFromCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + $this->graphQlQuery($query); + } + /** * Generates GraphQl query for retrieving cart totals * * @param string $maskedQuoteId * @return string */ - private function getCartTotalsGraphqlQuery(string $maskedQuoteId): string + private function getQuery(string $maskedQuoteId): string { return <<<QUERY { @@ -154,16 +165,4 @@ private function getCartTotalsGraphqlQuery(string $maskedQuoteId): string } QUERY; } - - /** - * @param string $reversedQuoteId - * @return string - */ - private function getMaskedQuoteIdByReversedQuoteId(string $reversedQuoteId): string - { - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id'); - - return $this->quoteIdToMaskedId->execute((int)$quote->getId()); - } } From 14de1708037321ec9481465dfe1ac6ffaf2fb4ee Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Mon, 15 Apr 2019 12:46:21 -0500 Subject: [PATCH 505/603] MAGETWO-99091: Name of categories in the Category tree on Product Edit page is not displayed according to the selected store view scope - Added strict types declaration - Added scalar type hints for new methods --- .../DataProvider/Product/Form/Modifier/Categories.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php index 8dc4b8100345e..db80d110e123a 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php @@ -3,6 +3,8 @@ * 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\Catalog\Model\Locator\LocatorInterface; @@ -313,7 +315,7 @@ protected function customizeCategoriesField(array $meta) */ protected function getCategoriesTree($filter = null) { - $storeId = $this->locator->getStore()->getId(); + $storeId = (int) $this->locator->getStore()->getId(); $cachedCategoriesTree = $this->getCacheManager() ->load($this->getCategoriesTreeCacheId($storeId, (string) $filter)); @@ -345,7 +347,7 @@ protected function getCategoriesTree($filter = null) * @param string $filter * @return string */ - private function getCategoriesTreeCacheId($storeId, $filter = '') + private function getCategoriesTreeCacheId(int $storeId, string $filter = '') : string { return self::CATEGORY_TREE_ID . '_' . (string) $storeId @@ -360,7 +362,7 @@ private function getCategoriesTreeCacheId($storeId, $filter = '') * @return array * @throws LocalizedException */ - private function retrieveShownCategoriesIds($storeId, $filter = '') + private function retrieveShownCategoriesIds(int $storeId, string $filter = '') : array { /* @var $matchingNamesCollection \Magento\Catalog\Model\ResourceModel\Category\Collection */ $matchingNamesCollection = $this->categoryCollectionFactory->create(); @@ -396,7 +398,7 @@ private function retrieveShownCategoriesIds($storeId, $filter = '') * @return array * @throws LocalizedException */ - private function retrieveCategoriesTree($storeId, array $shownCategoriesIds = []) + private function retrieveCategoriesTree(int $storeId, array $shownCategoriesIds) : array { /* @var $collection \Magento\Catalog\Model\ResourceModel\Category\Collection */ $collection = $this->categoryCollectionFactory->create(); From 259ee45bcfc4f0db2b74d42518f62f4583d5a41b Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 15 Apr 2019 14:49:14 -0500 Subject: [PATCH 506/603] GraphQL-281: [Shipping methods] Support of UPS shipping method --- .../Ups/SetUpsShippingMethodsOnCartTest.php | 373 ++---------------- 1 file changed, 28 insertions(+), 345 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index b41c7d0898f79..cfaf53e690c6c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -29,7 +29,7 @@ * | XDM | Worldwide Express Plus * | XPD | Worldwide Expedited * - * Current class does not cover these UPS shipping methods (depends on sandbox settings) + * Current class does not cover these UPS shipping methods (depends on address and sandbox settings) * * | Code | Label * -------------------------------------- @@ -81,197 +81,26 @@ protected function setUp() $objectManager = Bootstrap::getObjectManager(); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); - $this->getQuoteShippingAddressIdByReservedQuoteId = $objectManager->get(GetQuoteShippingAddressIdByReservedQuoteId::class); - } - - /** - * Set "Next Day Air Early AM" UPS shipping method - * - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php - */ - public function testSetNextDayAirEarlyAmUpsShippingMethod() - { - $quoteReservedId = 'test_quote'; - $methodCode = '1DM'; - $methodLabel = 'Next Day Air Early AM'; - - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); - $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - - $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); - $response = $this->sendRequestWithToken($query); - - self::assertArrayHasKey('setShippingMethodsOnCart', $response); - self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); - self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); - self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - - $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - self::assertArrayHasKey('selected_shipping_method', $shippingAddress); - - self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); - self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); - - self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); - - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_LABEL . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['label'] - ); - } - - /** - * Set "Next Day Air" UPS shipping method - * - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php - */ - public function testSetNextDayAirUpsShippingMethod() - { - $quoteReservedId = 'test_quote'; - $methodCode = '1DA'; - $methodLabel = 'Next Day Air'; - - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); - $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - - $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); - $response = $this->sendRequestWithToken($query); - - self::assertArrayHasKey('setShippingMethodsOnCart', $response); - self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); - self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); - self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - - $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - self::assertArrayHasKey('selected_shipping_method', $shippingAddress); - - self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); - self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); - - self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); - - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_LABEL . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['label'] + $this->getQuoteShippingAddressIdByReservedQuoteId = $objectManager->get( + GetQuoteShippingAddressIdByReservedQuoteId::class ); } /** - * Set "2nd Day Air" UPS shipping method - * * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php - */ - public function testSet2ndDayAirUpsShippingMethod() - { - $quoteReservedId = 'test_quote'; - $methodCode = '2DA'; - $methodLabel = '2nd Day Air'; - - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); - $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - - $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); - $response = $this->sendRequestWithToken($query); - - self::assertArrayHasKey('setShippingMethodsOnCart', $response); - self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); - self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); - self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - - $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - self::assertArrayHasKey('selected_shipping_method', $shippingAddress); - - self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); - self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); - - self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); - - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_LABEL . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['label'] - ); - } - - /** - * Set "3 Day Select" UPS shipping method * - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php - */ - public function testSet3DaySelectUpsShippingMethod() - { - $quoteReservedId = 'test_quote'; - $methodCode = '3DS'; - $methodLabel = '3 Day Select'; - - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); - $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - - $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); - $response = $this->sendRequestWithToken($query); - - self::assertArrayHasKey('setShippingMethodsOnCart', $response); - self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); - self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); - self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - - $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - self::assertArrayHasKey('selected_shipping_method', $shippingAddress); - - self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); - self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); - - self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); - - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_LABEL . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['label'] - ); - } - - /** - * Set "Ground" UPS shipping method - * - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php + * @dataProvider dataProviderShippingMethods + * @param string $methodCode + * @param string $methodLabel */ - public function testSetGroundUpsShippingMethod() + public function testSetUpsShippingMethod(string $methodCode, string $methodLabel) { $quoteReservedId = 'test_quote'; - $methodCode = 'GND'; - $methodLabel = 'Ground'; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); @@ -300,150 +129,34 @@ public function testSetGroundUpsShippingMethod() } /** - * Set "Canada Standard" UPS shipping method - * - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_canada_address.php - * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php + * @return array */ - public function testSetCanadaStandardUpsShippingMethod() + public function dataProviderShippingMethods(): array { - $quoteReservedId = 'test_quote'; - $methodCode = 'STD'; - $methodLabel = 'Canada Standard'; - - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); - $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - - $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); - $response = $this->sendRequestWithToken($query); - - self::assertArrayHasKey('setShippingMethodsOnCart', $response); - self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); - self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); - self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - - $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - self::assertArrayHasKey('selected_shipping_method', $shippingAddress); - - self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); - self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); - - self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); - - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_LABEL . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['label'] - ); + return [ + 'Next Day Air Early AM' => ['1DM', 'Next Day Air Early AM'], + 'Next Day Air' => ['1DA', 'Next Day Air'], + '2nd Day Air' => ['2DA', '2nd Day Air'], + '3 Day Select' => ['3DS', '3 Day Select'], + 'Ground' => ['GND', 'Ground'], + ]; } /** - * Set "Worldwide Express" UPS shipping method - * * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_canada_address.php * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php - */ - public function testSetWorldwideExpressUpsShippingMethod() - { - $quoteReservedId = 'test_quote'; - $methodCode = 'XPR'; - $methodLabel = 'Worldwide Express'; - - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); - $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - - $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); - $response = $this->sendRequestWithToken($query); - - self::assertArrayHasKey('setShippingMethodsOnCart', $response); - self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); - self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); - self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - - $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - self::assertArrayHasKey('selected_shipping_method', $shippingAddress); - - self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); - self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); - - self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); - - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_LABEL . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['label'] - ); - } - - /** - * Set "Worldwide Express Saver" UPS shipping method * - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_canada_address.php - * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php - */ - public function testSetWorldwideExpressSaverUpsShippingMethod() - { - $quoteReservedId = 'test_quote'; - $methodCode = 'WXS'; - $methodLabel = 'Worldwide Express Saver'; - - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); - $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - - $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); - $response = $this->sendRequestWithToken($query); - - self::assertArrayHasKey('setShippingMethodsOnCart', $response); - self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); - self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); - self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - - $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - self::assertArrayHasKey('selected_shipping_method', $shippingAddress); - - self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); - self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); - - self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); - - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_LABEL . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['label'] - ); - } - - /** - * Set "Worldwide Express Plus" UPS shipping method - * - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_canada_address.php - * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php + * @dataProvider dataProviderShippingMethodsBasedOnCanadaAddress + * @param string $methodCode + * @param string $methodLabel */ - public function testSetWorldwideExpressPlusUpsShippingMethod() + public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, string $methodLabel) { $quoteReservedId = 'test_quote'; - $methodCode = 'XDM'; - $methodLabel = 'Worldwide Express Plus'; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); @@ -472,46 +185,16 @@ public function testSetWorldwideExpressPlusUpsShippingMethod() } /** - * Set "Worldwide Expedited" UPS shipping method - * - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_canada_address.php - * @magentoApiDataFixture Magento/GraphQl/Ups/_files/enable_ups_shipping_method.php + * @return array */ - public function testSetWorldwideExpeditedUpsShippingMethod() + public function dataProviderShippingMethodsBasedOnCanadaAddress(): array { - $quoteReservedId = 'test_quote'; - $methodCode = 'XPD'; - $methodLabel = 'Worldwide Expedited'; - - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); - $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - - $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); - $response = $this->sendRequestWithToken($query); - - self::assertArrayHasKey('setShippingMethodsOnCart', $response); - self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); - self::assertArrayHasKey('shipping_addresses', $response['setShippingMethodsOnCart']['cart']); - self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - - $shippingAddress = current($response['setShippingMethodsOnCart']['cart']['shipping_addresses']); - self::assertArrayHasKey('selected_shipping_method', $shippingAddress); - - self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); - self::assertEquals(self::CARRIER_CODE, $shippingAddress['selected_shipping_method']['carrier_code']); - - self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); - - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_LABEL . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['label'] - ); + return [ + 'Canada Standard' => ['STD', 'Canada Standard'], + 'Worldwide Express' => ['XPR', 'Worldwide Express'], + 'Worldwide Express Saver' => ['WXS', 'Worldwide Express Saver'], + 'Worldwide Express Plus' => ['XDM', 'Worldwide Express Plus'], + ]; } /** From 679d8a542dedf330ee899332fd46a7d701c44071 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Mon, 15 Apr 2019 15:47:19 -0500 Subject: [PATCH 507/603] MC-15785: Overall storefront improvements --- .../templates/product/list/items.phtml | 2 +- .../view/frontend/web/js/related-products.js | 2 +- .../CheckoutShippingGuestInfoSection.xml | 2 +- .../Mftf/Section/CheckoutShippingSection.xml | 2 +- .../templates/cart/item/default.phtml | 26 +++++------ .../frontend/web/template/authentication.html | 10 ++--- .../web/template/form/element/email.html | 4 +- .../web/template/summary/cart-items.html | 2 +- .../view/frontend/templates/subscribe.phtml | 20 ++++++--- .../view/frontend/templates/form.mini.phtml | 43 +++++++++++-------- .../Search/view/frontend/web/js/form-mini.js | 1 - .../frontend/templates/html/header/logo.phtml | 6 ++- .../form/element/helper/tooltip.html | 16 ++++--- .../css/source/module/checkout/_tooltip.less | 4 ++ .../layout/default_head_blocks.xml | 2 +- 15 files changed, 85 insertions(+), 57 deletions(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml index f434402346087..ecc9700802d27 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml @@ -169,7 +169,7 @@ switch ($type = $block->getType()) { <?php if ($type == 'related' && $canItemsAddToCart): ?> <div class="block-actions"> <?= /* @escapeNotVerified */ __('Check items to add to the cart or') ?> - <button type="button" class="action select" role="select-all"><span><?= /* @escapeNotVerified */ __('select all') ?></span></button> + <button type="button" class="action select" role="button"><span><?= /* @escapeNotVerified */ __('select all') ?></span></button> </div> <?php endif; ?> <div class="products wrapper grid products-grid products-<?= /* @escapeNotVerified */ $type ?>"> diff --git a/app/code/Magento/Catalog/view/frontend/web/js/related-products.js b/app/code/Magento/Catalog/view/frontend/web/js/related-products.js index 0c37f9ff4f007..66df48c28bfab 100644 --- a/app/code/Magento/Catalog/view/frontend/web/js/related-products.js +++ b/app/code/Magento/Catalog/view/frontend/web/js/related-products.js @@ -17,7 +17,7 @@ define([ relatedProductsField: '#related-products-field', // Hidden input field that stores related products. selectAllMessage: $.mage.__('select all'), unselectAllMessage: $.mage.__('unselect all'), - selectAllLink: '[role="select-all"]', + selectAllLink: '[role="button"]', elementsSelector: '.item.product' }, diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml index 6838824400b96..d446990b12660 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="CheckoutShippingGuestInfoSection"> - <element name="email" type="input" selector="#customer-email"/> + <element name="email" type="input" selector="#checkout-customer-email"/> <element name="firstName" type="input" selector="input[name=firstname]"/> <element name="lastName" type="input" selector="input[name=lastname]"/> <element name="street" type="input" selector="input[name='street[0]']"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml index d825e10395145..9676f16f3a5c6 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml @@ -15,7 +15,7 @@ <element name="editAddressButton" type="button" selector=".action-edit-address" timeout="30"/> <element name="addressDropdown" type="select" selector="[name=billing_address_id]"/> <element name="newAddressButton" type="button" selector=".action-show-popup" timeout="30"/> - <element name="email" type="input" selector="#customer-email"/> + <element name="email" type="input" selector="#checkout-customer-email"/> <element name="firstName" type="input" selector="input[name=firstname]"/> <element name="lastName" type="input" selector="input[name=lastname]"/> <element name="company" type="input" selector="input[name=company]"/> 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 454031279d882..d15794fb761bb 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 @@ -84,20 +84,20 @@ $canApplyMsrp = $helper->isShowBeforeOrderConfirm($product) && $helper->isMinima <?php endif; ?> <td class="col qty" data-th="<?= $block->escapeHtml(__('Qty')) ?>"> <div class="field qty"> - <label class="label" for="cart-<?= /* @escapeNotVerified */ $_item->getId() ?>-qty"> - <span><?= /* @escapeNotVerified */ __('Qty') ?></span> - </label> <div class="control qty"> - <input id="cart-<?= /* @escapeNotVerified */ $_item->getId() ?>-qty" - name="cart[<?= /* @escapeNotVerified */ $_item->getId() ?>][qty]" - data-cart-item-id="<?= $block->escapeHtml($_item->getSku()) ?>" - value="<?= /* @escapeNotVerified */ $block->getQty() ?>" - type="number" - size="4" - title="<?= $block->escapeHtml(__('Qty')) ?>" - class="input-text qty" - data-validate="{required:true,'validate-greater-than-zero':true}" - data-role="cart-item-qty"/> + <label for="cart-<?= /* @escapeNotVerified */ $_item->getId() ?>-qty"> + <span class="label"><?= /* @escapeNotVerified */ __('Qty') ?></span> + <input id="cart-<?= /* @escapeNotVerified */ $_item->getId() ?>-qty" + name="cart[<?= /* @escapeNotVerified */ $_item->getId() ?>][qty]" + data-cart-item-id="<?= $block->escapeHtml($_item->getSku()) ?>" + value="<?= /* @escapeNotVerified */ $block->getQty() ?>" + type="number" + size="4" + title="<?= $block->escapeHtml(__('Qty')) ?>" + class="input-text qty" + data-validate="{required:true,'validate-greater-than-zero':true}" + data-role="cart-item-qty"/> + </label> </div> </div> </td> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/authentication.html b/app/code/Magento/Checkout/view/frontend/web/template/authentication.html index 406a7d899b67a..5b8dde81dd93e 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/authentication.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/authentication.html @@ -31,15 +31,15 @@ <div class="block block-customer-login" data-bind="attr: {'data-label': $t('or')}"> <div class="block-title"> - <strong id="block-customer-login-heading" - role="heading" - aria-level="2" - data-bind="i18n: 'Sign In'"></strong> + <strong id="block-customer-login-heading-checkout" + role="heading" + aria-level="2" + data-bind="i18n: 'Sign In'"></strong> </div> <!-- ko foreach: getRegion('messages') --> <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> - <div class="block-content" aria-labelledby="block-customer-login-heading"> + <div class="block-content" aria-labelledby="block-customer-login-heading-checkout"> <form data-role="login" data-bind="submit:login" method="post"> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/form/element/email.html b/app/code/Magento/Checkout/view/frontend/web/template/form/element/email.html index 8d6142e07fcf0..6a784fa7a04c4 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/form/element/email.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/form/element/email.html @@ -14,7 +14,7 @@ method="post"> <fieldset id="customer-email-fieldset" class="fieldset" data-bind="blockLoader: isLoading"> <div class="field required"> - <label class="label" for="customer-email"> + <label class="label" for="checkout-customer-email"> <span data-bind="i18n: 'Email Address'"></span> </label> <div class="control _with-tooltip"> @@ -26,7 +26,7 @@ mageInit: {'mage/trim-input':{}}" name="username" data-validate="{required:true, 'validate-email':true}" - id="customer-email" /> + id="checkout-customer-email" /> <!-- ko template: 'ui/form/element/helper/tooltip' --><!-- /ko --> <span class="note" data-bind="fadeVisible: isPasswordVisible() == false"><!-- ko i18n: 'You can create an account after checkout.'--><!-- /ko --></span> </div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html index 34ec91aa43c72..fc74a4691a2e7 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html @@ -6,7 +6,7 @@ --> <div class="block items-in-cart" data-bind="mageInit: {'collapsible':{'openedState': 'active', 'active': isItemsBlockExpanded()}}"> <div class="title" data-role="title"> - <strong role="heading"> + <strong role="heading" aria-level="1"> <translate args="maxCartItemsToDisplay" if="maxCartItemsToDisplay < getCartLineItemsCount()"/> <translate args="'of'" if="maxCartItemsToDisplay < getCartLineItemsCount()"/> <span data-bind="text: getCartLineItemsCount()"></span> diff --git a/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml b/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml index c1a526ee95148..554437095f36c 100644 --- a/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml +++ b/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml @@ -19,16 +19,24 @@ data-mage-init='{"validation": {"errorClass": "mage-error"}}' id="newsletter-validate-detail"> <div class="field newsletter"> - <label class="label" for="newsletter"><span><?= $block->escapeHtml(__('Sign Up for Our Newsletter:')) ?></span></label> <div class="control"> - <input name="email" type="email" id="newsletter" - placeholder="<?= $block->escapeHtml(__('Enter your email address')) ?>" - data-mage-init='{"mage/trim-input":{}}' - data-validate="{required:true, 'validate-email':true}"/> + <label for="newsletter"> + <span class="label"> + <?= $block->escapeHtml(__('Sign Up for Our Newsletter:')) ?> + </span> + <input name="email" type="email" id="newsletter" + placeholder="<?= $block->escapeHtml(__('Enter your email address')) ?>" + data-mage-init='{"mage/trim-input":{}}' + data-validate="{required:true, 'validate-email':true}" + /> + </label> </div> </div> <div class="actions"> - <button class="action subscribe primary" title="<?= $block->escapeHtmlAttr(__('Subscribe')) ?>" type="submit"> + <button class="action subscribe primary sr-only" + title="<?= $block->escapeHtmlAttr(__('Subscribe')) ?>" + type="submit" + aria-label="Subscribe"> <span><?= $block->escapeHtml(__('Subscribe')) ?></span> </button> </div> diff --git a/app/code/Magento/Search/view/frontend/templates/form.mini.phtml b/app/code/Magento/Search/view/frontend/templates/form.mini.phtml index 2ea87be13d5e3..a98a70a90cede 100644 --- a/app/code/Magento/Search/view/frontend/templates/form.mini.phtml +++ b/app/code/Magento/Search/view/frontend/templates/form.mini.phtml @@ -16,34 +16,41 @@ $helper = $this->helper(\Magento\Search\Helper\Data::class); <div class="block block-content"> <form class="form minisearch" id="search_mini_form" action="<?= /* @escapeNotVerified */ $helper->getResultUrl() ?>" method="get"> <div class="field search"> - <label class="label" for="search" data-role="minisearch-label"> - <span><?= /* @escapeNotVerified */ __('Search') ?></span> - </label> <div class="control"> - <input id="search" - data-mage-init='{"quickSearch":{ + <label for="search" data-role="minisearch-label"> + <span class="label"> + <?= /* @escapeNotVerified */ __('Search') ?> + </span> + <input + aria-expanded="false" + id="search" + data-mage-init='{"quickSearch":{ "formSelector":"#search_mini_form", "url":"<?= /* @escapeNotVerified */ $helper->getSuggestUrl()?>", "destinationSelector":"#search_autocomplete"} - }' - type="text" - name="<?= /* @escapeNotVerified */ $helper->getQueryParamName() ?>" - value="<?= /* @escapeNotVerified */ $helper->getEscapedQueryText() ?>" - placeholder="<?= /* @escapeNotVerified */ __('Search entire store here...') ?>" - class="input-text" - maxlength="<?= /* @escapeNotVerified */ $helper->getMaxQueryLength() ?>" - role="combobox" - aria-haspopup="false" - aria-autocomplete="both" - autocomplete="off"/> + }' + type="text" + name="<?= /* @escapeNotVerified */ $helper->getQueryParamName() ?>" + value="<?= /* @escapeNotVerified */ $helper->getEscapedQueryText() ?>" + placeholder="<?= /* @escapeNotVerified */ __('Search entire store here...') ?>" + class="input-text" + maxlength="<?= /* @escapeNotVerified */ $helper->getMaxQueryLength() ?>" + role="combobox" + aria-haspopup="false" + aria-autocomplete="both" + autocomplete="off" + /> + </label> <div id="search_autocomplete" class="search-autocomplete"></div> <?= $block->getChildHtml() ?> </div> </div> <div class="actions"> <button type="submit" - title="<?= $block->escapeHtml(__('Search')) ?>" - class="action search"> + title="<?= $block->escapeHtml(__('Search')) ?>" + class="action search" + aria-label="Search" + > <span><?= /* @escapeNotVerified */ __('Search') ?></span> </button> </div> 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 15bcf2e73393e..5331ba3b447ac 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 @@ -72,7 +72,6 @@ define([ }.bind(this), exit: function () { this.isExpandable = false; - this.element.removeAttr('aria-expanded'); }.bind(this) }); diff --git a/app/code/Magento/Theme/view/frontend/templates/html/header/logo.phtml b/app/code/Magento/Theme/view/frontend/templates/html/header/logo.phtml index f719f5dd78307..9c34dfea3218b 100644 --- a/app/code/Magento/Theme/view/frontend/templates/html/header/logo.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/html/header/logo.phtml @@ -12,7 +12,11 @@ ?> <?php $storeName = $block->getThemeName() ? $block->getThemeName() : $block->getLogoAlt();?> <span data-action="toggle-nav" class="action nav-toggle"><span><?= /* @escapeNotVerified */ __('Toggle Nav') ?></span></span> -<a class="logo" href="<?= $block->getUrl('') ?>" title="<?= /* @escapeNotVerified */ $storeName ?>"> +<a + class="logo" + href="<?= $block->getUrl('') ?>" + title="<?= /* @escapeNotVerified */ $storeName ?>" + aria-label="store logo"> <img src="<?= /* @escapeNotVerified */ $block->getLogoSrc() ?>" title="<?= $block->escapeHtmlAttr($block->getLogoAlt()) ?>" alt="<?= $block->escapeHtmlAttr($block->getLogoAlt()) ?>" diff --git a/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html b/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html index 3d4f9eefe5afa..fd4ee0ad88da9 100644 --- a/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html +++ b/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html @@ -13,14 +13,20 @@ data-bind="attr: {href: tooltip.link}, mageInit: {'dropdown':{'activeClass': '_active'}}"></a> <!-- /ko --> + <span id="tooltip-label" class="label">Tooltip</span> <!-- ko if: (!tooltip.link)--> - <span class="field-tooltip-action action-help" - tabindex="0" - data-toggle="dropdown" - data-bind="mageInit: {'dropdown':{'activeClass': '_active'}}"></span> + <span + id="tooltip" + class="field-tooltip-action action-help" + tabindex="0" + data-toggle="dropdown" + data-bind="mageInit: {'dropdown':{'activeClass': '_active', 'parent': '.field-tooltip.toggle'}}" + aria-labelledby="tooltip-label" + > + </span> <!-- /ko --> - <div class="field-tooltip-content" + <div class="field-tooltip-content" data-target="dropdown" translate="tooltip.description"> </div> </div> diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less index 664726ddfd798..f958d7081f963 100644 --- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less @@ -55,6 +55,10 @@ } } + .label { + .lib-visually-hidden(); + } + .field-tooltip-action { .lib-icon-font( @checkout-tooltip-icon__content, diff --git a/app/design/frontend/Magento/luma/Magento_Theme/layout/default_head_blocks.xml b/app/design/frontend/Magento/luma/Magento_Theme/layout/default_head_blocks.xml index 2dfb1d3ee6bf0..7e64e5f3f01cd 100644 --- a/app/design/frontend/Magento/luma/Magento_Theme/layout/default_head_blocks.xml +++ b/app/design/frontend/Magento/luma/Magento_Theme/layout/default_head_blocks.xml @@ -7,6 +7,6 @@ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <head> - <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"/> + <meta name="viewport" content="width=device-width, initial-scale=1"/> </head> </page> From c81353d878168776e4bec5b164e9bdaab1e899c8 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 15 Apr 2019 16:21:33 -0500 Subject: [PATCH 508/603] GraphQL-564: [Checkout coverage] setGuestEmailOnCart mutation --- .../GraphQl/Quote/Guest/PlaceOrderTest.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php index 31f60afc1331f..30ad69eada29d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/PlaceOrderTest.php @@ -69,7 +69,7 @@ public function testPlaceOrder() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); $query = $this->getQuery($maskedQuoteId); - $response = $this->graphQlQuery($query); + $response = $this->graphQlMutation($query); self::assertArrayHasKey('placeOrder', $response); self::assertArrayHasKey('order_id', $response['placeOrder']['order']); @@ -94,7 +94,7 @@ public function testPlaceOrderWithNoEmail() $query = $this->getQuery($maskedQuoteId); self::expectExceptionMessage("Guest email for cart is missing. Please enter"); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -111,7 +111,7 @@ public function testPlaceOrderWithNoItemsInCart() 'Unable to place order: A server error stopped your order from being placed. ' . 'Please try to place your order again' ); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -129,7 +129,7 @@ public function testPlaceOrderWithNoShippingAddress() self::expectExceptionMessage( 'Unable to place order: Some addresses can\'t be used due to the configurations for specific countries' ); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -148,7 +148,7 @@ public function testPlaceOrderWithNoShippingMethod() self::expectExceptionMessage( 'Unable to place order: The shipping method is missing. Select the shipping method and try again' ); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -169,7 +169,7 @@ public function testPlaceOrderWithNoBillingAddress() self::expectExceptionMessageRegExp( '/Unable to place order: Please check the billing address information*/' ); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -189,7 +189,7 @@ public function testPlaceOrderWithNoPaymentMethod() $query = $this->getQuery($maskedQuoteId); self::expectExceptionMessage('Unable to place order: Enter a valid payment method and try again'); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -210,7 +210,7 @@ public function testPlaceOrderWithOutOfStockProduct() $query = $this->getQuery($maskedQuoteId); self::expectExceptionMessage('Unable to place order: Some of the products are out of stock'); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** @@ -233,7 +233,7 @@ public function testPlaceOrderOfCustomerCart() $query = $this->getQuery($maskedQuoteId); self::expectExceptionMessageRegExp('/The current user cannot perform operations on cart*/'); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } /** From f2d3539ff6e5a24f7619f30d3e8ce88e777ad51c Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Tue, 16 Apr 2019 08:41:48 +0300 Subject: [PATCH 509/603] magento/graphql-ce#540: Replace deprecated fixture 1. Add "Worldwide Expedited" to test --- .../Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index cfaf53e690c6c..fb0c205c86a2c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -194,6 +194,7 @@ public function dataProviderShippingMethodsBasedOnCanadaAddress(): array 'Worldwide Express' => ['XPR', 'Worldwide Express'], 'Worldwide Express Saver' => ['WXS', 'Worldwide Express Saver'], 'Worldwide Express Plus' => ['XDM', 'Worldwide Express Plus'], + 'Worldwide Expedited' => ['XPD', 'Worldwide Expedited'], ]; } From 71463ddc1897200ded1cfd27100c824fe9ead5c2 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Tue, 16 Apr 2019 10:53:43 +0300 Subject: [PATCH 510/603] MC-11943: Cancel Created Order for Offline Payment Methods --- .../app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml index e45609bb90c83..fdb396bbbd052 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml @@ -18,7 +18,6 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" /> </variation> <variation name="CancelCreatedOrderTestVariationWithZeroSubtotalCheckout" summary="Cancel order with zero subtotal checkout payment method and check status on storefront"> - <data name="tag" xsi:type="string">stable:no</data> <data name="order/dataset" xsi:type="string">default</data> <data name="order/data/payment_auth_expiration/method" xsi:type="string">free</data> <data name="order/data/shipping_method" xsi:type="string">freeshipping_freeshipping</data> From d4972dcde417536ab676a5a26b2f507299aa289c Mon Sep 17 00:00:00 2001 From: niravkrish <nirav.patel@krishtechnolabs.com> Date: Tue, 16 Apr 2019 14:38:49 +0530 Subject: [PATCH 511/603] Fixed - Category API update Issue required name on update --- app/code/Magento/Catalog/Api/Data/CategoryInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Api/Data/CategoryInterface.php b/app/code/Magento/Catalog/Api/Data/CategoryInterface.php index b9a23e9d08ec3..c1ca89f51ea58 100644 --- a/app/code/Magento/Catalog/Api/Data/CategoryInterface.php +++ b/app/code/Magento/Catalog/Api/Data/CategoryInterface.php @@ -74,7 +74,7 @@ public function setParentId($parentId); /** * Get category name * - * @return string + * @return string|null */ public function getName(); From 96b11759a3fae5d264026adf8740ae6ed437dc83 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Tue, 16 Apr 2019 13:39:54 +0300 Subject: [PATCH 512/603] MC-12180: Verify that information about viewing, comparison, wishlist and last ordered items is persisted under long-term cookie --- .../Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml index dbe5ddcc366f1..87aab45bd8cb7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontWidgetsSection.xml @@ -9,8 +9,8 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontWidgetsSection"> - <element name="widgetRecentlyViewedProductsGrid" type="block" selector=".block.widget.block-viewed-products-grid" timeout="30"/> - <element name="widgetRecentlyComparedProductsGrid" type="block" selector=".block.widget.block-compared-products-grid" timeout="30"/> - <element name="widgetRecentlyOrderedProductsGrid" type="block" selector=".block.block-reorder" timeout="30"/> + <element name="widgetRecentlyViewedProductsGrid" type="block" selector=".block.widget.block-viewed-products-grid"/> + <element name="widgetRecentlyComparedProductsGrid" type="block" selector=".block.widget.block-compared-products-grid"/> + <element name="widgetRecentlyOrderedProductsGrid" type="block" selector=".block.block-reorder"/> </section> </sections> \ No newline at end of file From 251eab09b0e01f657b8d908fcc49588aa3d80d98 Mon Sep 17 00:00:00 2001 From: Nikita Fomin <fmnnkt@gmail.com> Date: Tue, 16 Apr 2019 13:53:01 +0300 Subject: [PATCH 513/603] MC-11954: Admin Global Search --- .../Magento/Backend/Test/TestCase/GlobalSearchEntityTest.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/GlobalSearchEntityTest.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/GlobalSearchEntityTest.xml index dca6e1d15024f..6d9c50b4317c8 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/GlobalSearchEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/GlobalSearchEntityTest.xml @@ -8,31 +8,26 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Backend\Test\TestCase\GlobalSearchEntityTest" summary="Global Search Backend " ticketId="MAGETWO-28457"> <variation name="GlobalSearchEntityTestVariation1"> - <data name="tag" xsi:type="string">stable:no</data> <data name="description" xsi:type="string">search shows admin preview</data> <data name="search/data/query" xsi:type="string">Some search term</data> <constraint name="Magento\Backend\Test\Constraint\AssertGlobalSearchPreview" /> </variation> <variation name="GlobalSearchEntityTestVariation2"> - <data name="tag" xsi:type="string">stable:no</data> <data name="description" xsi:type="string">search with 2 sign return no results</data> <data name="search/data/query" xsi:type="string">:)</data> <constraint name="Magento\Backend\Test\Constraint\AssertGlobalSearchNoRecordsFound" /> </variation> <variation name="GlobalSearchEntityTestVariation3"> - <data name="tag" xsi:type="string">stable:no</data> <data name="description" xsi:type="string">search product by sku</data> <data name="search/data/query" xsi:type="string">orderInjectable::default::product::sku</data> <constraint name="Magento\Backend\Test\Constraint\AssertGlobalSearchProductName" /> </variation> <variation name="GlobalSearchEntityTestVariation4"> - <data name="tag" xsi:type="string">stable:no</data> <data name="description" xsi:type="string">search existed customer</data> <data name="search/data/query" xsi:type="string">customer::johndoe_unique::lastname</data> <constraint name="Magento\Backend\Test\Constraint\AssertGlobalSearchCustomerName" /> </variation> <variation name="GlobalSearchEntityTestVariation5"> - <data name="tag" xsi:type="string">stable:no</data> <data name="description" xsi:type="string">search order (by order id)</data> <data name="search/data/query" xsi:type="string">orderInjectable::default::id</data> <constraint name="Magento\Backend\Test\Constraint\AssertGlobalSearchOrderId" /> From 266c55250024f2d874c37ad811e10c41a053e7a4 Mon Sep 17 00:00:00 2001 From: Mikalai Shostka <mikalai_shostka@epam.com> Date: Tue, 16 Apr 2019 14:20:14 +0300 Subject: [PATCH 514/603] MAGETWO-64260: [Optimize] Performance for grouped products with large # of options - Fix static test; --- app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php index c362474e3cf68..187fd27fa0554 100644 --- a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php +++ b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php @@ -475,10 +475,12 @@ public function hasWeight() * @param \Magento\Catalog\Model\Product $product * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * phpcs:disable Magento2.CodeAnalysis.EmptyBlock */ public function deleteTypeSpecificData(\Magento\Catalog\Model\Product $product) { } + //phpcs:enable /** * @inheritdoc @@ -488,6 +490,7 @@ public function beforeSave($product) //clear cached associated links $product->unsetData($this->_keyAssociatedProducts); if ($product->hasData('product_options') && !empty($product->getData('product_options'))) { + //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Custom options for grouped product type are not supported'); } return parent::beforeSave($product); From 3c50c7ceed1728d3886131b29ea2e0d937a68b97 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 12 Apr 2019 16:47:12 +0300 Subject: [PATCH 515/603] magento/magento2#21772: Static test fix. --- .../Adapter/Mysql/Filter/Preprocessor.php | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php index 51eb2077b80ea..c758e773f43c1 100644 --- a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php +++ b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php @@ -8,7 +8,9 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\ResourceModel\Eav\Attribute; +use Magento\CatalogSearch\Model\Search\FilterMapper\VisibilityFilter; use Magento\CatalogSearch\Model\Search\TableMapper; +use Magento\Customer\Model\Session; use Magento\Eav\Model\Config; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\ObjectManager; @@ -20,10 +22,11 @@ use Magento\Framework\Search\Adapter\Mysql\Filter\PreprocessorInterface; use Magento\Framework\Search\Request\FilterInterface; use Magento\Store\Model\Store; -use Magento\Customer\Model\Session; -use Magento\CatalogSearch\Model\Search\FilterMapper\VisibilityFilter; /** + * ElasticSearch search filter pre-processor. + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @deprecated * @see \Magento\ElasticSearch @@ -128,7 +131,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function process(FilterInterface $filter, $isNegation, $query) { @@ -136,10 +139,13 @@ public function process(FilterInterface $filter, $isNegation, $query) } /** + * Process query with field. + * * @param FilterInterface $filter * @param bool $isNegation * @param string $query * @return string + * @throws \Magento\Framework\Exception\LocalizedException */ private function processQueryWithField(FilterInterface $filter, $isNegation, $query) { @@ -204,19 +210,23 @@ private function processQueryWithField(FilterInterface $filter, $isNegation, $qu ->where('main_table.store_id = ?', Store::DEFAULT_STORE_ID) ->having($query); - $resultQuery = 'search_index.entity_id IN ( - select entity_id from ' . $this->conditionManager->wrapBrackets($select) . ' as filter - )'; + $resultQuery = 'search_index.entity_id IN (' + . 'select entity_id from ' + . $this->conditionManager->wrapBrackets($select) + . ' as filter)'; } return $resultQuery; } /** + * Process range numeric. + * * @param FilterInterface $filter * @param string $query * @param Attribute $attribute * @return string + * @throws \Exception */ private function processRangeNumeric(FilterInterface $filter, $query, $attribute) { @@ -238,14 +248,17 @@ private function processRangeNumeric(FilterInterface $filter, $query, $attribute ->where('main_table.store_id = ?', $currentStoreId) ->having($query); - $resultQuery = 'search_index.entity_id IN ( - select entity_id from ' . $this->conditionManager->wrapBrackets($select) . ' as filter - )'; + $resultQuery = 'search_index.entity_id IN (' + . 'select entity_id from ' + . $this->conditionManager->wrapBrackets($select) + . ' as filter)'; return $resultQuery; } /** + * Process term select. + * * @param FilterInterface $filter * @param bool $isNegation * @return string From 0c954cd5275f04a3469a5ea907125c0ccb10a04a Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 16 Apr 2019 15:16:19 +0300 Subject: [PATCH 516/603] magento/magento2#22200: Static test fix. --- pub/health_check.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pub/health_check.php b/pub/health_check.php index 06c79baa2fd81..fc6d73daa2079 100644 --- a/pub/health_check.php +++ b/pub/health_check.php @@ -4,11 +4,17 @@ * See COPYING.txt for license details. */ +/** + * phpcs:disable PSR1.Files.SideEffects + * phpcs:disable Squiz.Functions.GlobalFunction + */ use Magento\Framework\Config\ConfigOptionsListConstants; +// phpcs:ignore Magento2.Functions.DiscouragedFunction register_shutdown_function("fatalErrorHandler"); try { + // phpcs:ignore Magento2.Security.IncludeFile require __DIR__ . '/../app/bootstrap.php'; /** @var \Magento\Framework\App\ObjectManagerFactory $objectManagerFactory */ $objectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, []); @@ -20,6 +26,7 @@ $logger = $objectManager->get(\Psr\Log\LoggerInterface::class); } catch (\Exception $e) { http_response_code(500); + // phpcs:ignore Magento2.Security.LanguageConstruct exit(1); } @@ -35,6 +42,7 @@ } catch (\Exception $e) { http_response_code(500); $logger->error("MySQL connection failed: " . $e->getMessage()); + // phpcs:ignore Magento2.Security.LanguageConstruct exit(1); } } @@ -47,6 +55,7 @@ !isset($cacheConfig[ConfigOptionsListConstants::CONFIG_PATH_BACKEND_OPTIONS])) { http_response_code(500); $logger->error("Cache configuration is invalid"); + // phpcs:ignore Magento2.Security.LanguageConstruct exit(1); } $cacheBackendClass = $cacheConfig[ConfigOptionsListConstants::CONFIG_PATH_BACKEND]; @@ -57,6 +66,7 @@ } catch (\Exception $e) { http_response_code(500); $logger->error("Cache storage is not accessible"); + // phpcs:ignore Magento2.Security.LanguageConstruct exit(1); } } From 1a1eda6a26301b10d97b6b33ab5e3a195e212f94 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 16 Apr 2019 15:58:25 +0300 Subject: [PATCH 517/603] magento/magento2#22318: Static test fix. --- .../Catalog/Model/Indexer/Product/Flat/TableBuilder.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php index 0865c311e7094..2c32a74eb0f1d 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php @@ -304,9 +304,12 @@ protected function _fillTemporaryTable( /** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ foreach ($columnsList as $columnName => $attribute) { - $countTableName = 't' . $iterationNum++; + $countTableName = 't' . ($iterationNum++); $joinCondition = sprintf( - 'e.%3$s = %1$s.%3$s AND %1$s.attribute_id = %2$d AND (%1$s.store_id = %4$d OR %1$s.store_id = 0)', + 'e.%3$s = %1$s.%3$s' . + ' AND %1$s.attribute_id = %2$d' . + ' AND (%1$s.store_id = %4$d' . + ' OR %1$s.store_id = 0)', $countTableName, $attribute->getId(), $metadata->getLinkField(), From 0453184879c5957d7ec4c903b9148c8ea35e43c1 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 16 Apr 2019 16:18:59 +0300 Subject: [PATCH 518/603] magento/magento2#22291: Static test fix. --- .../Product/Downloads/Collection.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php index aeb0448f8e05a..2009cd3ff9d92 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Product/Downloads/Collection.php @@ -4,16 +4,16 @@ * See COPYING.txt for license details. */ +namespace Magento\Reports\Model\ResourceModel\Product\Downloads; + /** * Product Downloads Report collection * * @author Magento Core Team <core@magentocommerce.com> - */ -namespace Magento\Reports\Model\ResourceModel\Product\Downloads; - -/** + * * @api * @since 100.0.2 + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection { @@ -97,13 +97,11 @@ public function addFieldToFilter($field, $condition = null) } return $this; } - + /** - * Get SQL for get record count without left JOINs and group - * - * @return \Magento\Framework\DB\Select + * @inheritDoc */ - public function getSelectCountSql() + public function getSelectCountSql() { $countSelect = parent::getSelectCountSql(); $countSelect->reset(\Zend\Db\Sql\Select::GROUP); From f266f4bfe56415c3c225ac2fccf658dda59e5667 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Tue, 16 Apr 2019 16:59:54 +0300 Subject: [PATCH 519/603] Gix static tests. --- .../Adminhtml/System/Design/Theme/UploadJs.php | 6 +++++- app/code/Magento/Theme/Model/Design/Backend/File.php | 5 ++--- .../Model/Design/Config/FileUploader/FileProcessor.php | 2 ++ app/code/Magento/Theme/Model/Wysiwyg/Storage.php | 9 ++------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php index ce88315b6225b..89636ad3de50e 100644 --- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php +++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php @@ -4,13 +4,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Theme\Controller\Adminhtml\System\Design\Theme; +use Magento\Framework\App\Action\HttpGetActionInterface; + /** * Class UploadJs * @deprecated */ -class UploadJs extends \Magento\Theme\Controller\Adminhtml\System\Design\Theme +class UploadJs extends \Magento\Theme\Controller\Adminhtml\System\Design\Theme implements HttpGetActionInterface { /** * Upload js file @@ -49,6 +52,7 @@ public function execute() \Magento\Framework\View\Design\Theme\Customization\File\Js::TYPE ); $result = ['error' => false, 'files' => $customization->generateFileInfo($customJsFiles)]; + // phpcs:disable Magento2.Exceptions.ThrowCatch } catch (\Magento\Framework\Exception\LocalizedException $e) { $result = ['error' => true, 'message' => $e->getMessage()]; } catch (\Exception $e) { diff --git a/app/code/Magento/Theme/Model/Design/Backend/File.php b/app/code/Magento/Theme/Model/Design/Backend/File.php index 72ca9295ad12f..8d1884671c3fb 100644 --- a/app/code/Magento/Theme/Model/Design/Backend/File.php +++ b/app/code/Magento/Theme/Model/Design/Backend/File.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Theme\Model\Design\Backend; use Magento\Config\Model\Config\Backend\File\RequestData\RequestDataInterface; @@ -109,9 +110,7 @@ public function beforeSave() } /** - * @return $this - * - * @throws LocalizedException + * @inheritDoc */ public function afterLoad() { diff --git a/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php b/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php index 6da7cb74e6741..901dbf7d88f3d 100644 --- a/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php +++ b/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php @@ -18,6 +18,8 @@ use Magento\Store\Model\StoreManagerInterface; /** + * Design file processor. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class FileProcessor diff --git a/app/code/Magento/Theme/Model/Wysiwyg/Storage.php b/app/code/Magento/Theme/Model/Wysiwyg/Storage.php index f1a4b1ffc8d65..0519460c02423 100644 --- a/app/code/Magento/Theme/Model/Wysiwyg/Storage.php +++ b/app/code/Magento/Theme/Model/Wysiwyg/Storage.php @@ -4,17 +4,12 @@ * See COPYING.txt for license details. */ -/** - * Theme wysiwyg storage model - */ namespace Magento\Theme\Model\Wysiwyg; use Magento\Framework\App\Filesystem\DirectoryList; /** - * Class Storage - * - * @package Magento\Theme\Model\Wysiwyg + * Theme wysiwyg storage model */ class Storage { @@ -271,7 +266,7 @@ public function getFilesCollection() if (self::TYPE_IMAGE == $storageType) { $requestParams['file'] = $fileName; $file['thumbnailParams'] = $requestParams; - + //phpcs:ignore Generic.PHP.NoSilencedErrors $size = @getimagesize($path); if (is_array($size)) { $file['width'] = $size[0]; From fcb544f5a001701cf966b181d6b6871e1c628c2c Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Tue, 16 Apr 2019 17:30:49 +0300 Subject: [PATCH 520/603] MC-5270: Assign Products at the Category Level --- .../Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml index ea6808ee2a7f5..223aa57335b13 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml @@ -146,7 +146,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryPage" /> </variation> <variation name="CreateCategoryEntityTestVariation8_WithProducts" summary="Assign Products at the Category Level" ticketId="MAGETWO-16351"> - <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test, stable:no</data> + <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test</data> <data name="addCategory" xsi:type="string">addSubcategory</data> <data name="category/data/parent_id/dataset" xsi:type="string">default_category</data> <data name="category/data/is_active" xsi:type="string">Yes</data> From 85319f0ca56cd22911e3e46fdd6e4d86de352238 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 16 Apr 2019 17:32:18 +0300 Subject: [PATCH 521/603] magento/magento2#22133: Static test fix. --- .../Eav/Model/ResourceModel/Entity/Attribute/Collection.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php index d70e2e0e06e96..6fce6bd2dc44e 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model\ResourceModel\Entity\Attribute; use Magento\Eav\Model\Entity\Type; @@ -183,6 +184,7 @@ public function setAttributeSetFilterBySetName($attributeSetName, $entityTypeCod /** * Specify multiple attribute sets filter + * * Result will be ordered by sort_order * * @param array $setIds @@ -225,7 +227,6 @@ public function setInAllAttributeSetsFilter(array $setIds) ->having(new \Zend_Db_Expr('COUNT(*)') . ' = ' . count($setIds)); } - //$this->getSelect()->distinct(true); $this->setOrder('is_user_defined', self::SORT_ORDER_ASC); return $this; @@ -475,7 +476,7 @@ public function addStoreLabel($storeId) } /** - * {@inheritdoc} + * @inheritdoc */ public function getSelectCountSql() { From bb185021332e9b3f714f2cd26a0b854deb51a29b Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Tue, 16 Apr 2019 10:16:02 -0500 Subject: [PATCH 522/603] MC-15785: Overall storefront improvements --- .../frontend/web/templates/form/element/helper/tooltip.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html b/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html index fd4ee0ad88da9..f8d1cbbcad5c1 100644 --- a/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html +++ b/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html @@ -13,7 +13,7 @@ data-bind="attr: {href: tooltip.link}, mageInit: {'dropdown':{'activeClass': '_active'}}"></a> <!-- /ko --> - <span id="tooltip-label" class="label">Tooltip</span> + <span id="tooltip-label" class="label"><!-- ko i18n: 'Tooltip' --><!-- /ko --></span> <!-- ko if: (!tooltip.link)--> <span id="tooltip" From 03cb300cb527e82bfcc411ccde99a39d5af2c8e9 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Tue, 16 Apr 2019 11:45:24 -0500 Subject: [PATCH 523/603] MAGETWO-98853: reporting_system_updates table exceptionally large (4gb) --- .../NewRelicReporting/Model/Module/Collect.php | 4 +++- .../NewRelicReporting/Model/Module/CollectTest.php | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/NewRelicReporting/Model/Module/Collect.php b/app/code/Magento/NewRelicReporting/Model/Module/Collect.php index ac7e4df9331c3..fe5389e258aa5 100644 --- a/app/code/Magento/NewRelicReporting/Model/Module/Collect.php +++ b/app/code/Magento/NewRelicReporting/Model/Module/Collect.php @@ -11,6 +11,9 @@ use Magento\NewRelicReporting\Model\Config; use Magento\NewRelicReporting\Model\Module; +/** + * Class for collecting data for the report + */ class Collect { /** @@ -92,7 +95,6 @@ protected function getAllModules() * @param string $active * @param string $setupVersion * @param string $state - * * @return array */ protected function getNewModuleChanges($moduleName, $active, $setupVersion, $state) diff --git a/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php b/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php index 4243ca7ab626d..58759d35337bd 100644 --- a/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php +++ b/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php @@ -8,6 +8,11 @@ use Magento\TestFramework\Helper\Bootstrap; use PHPUnit\Framework\TestCase; +/*** + * Class CollectTest + * + * @covers Collect + */ class CollectTest extends TestCase { /** @@ -15,11 +20,17 @@ class CollectTest extends TestCase */ private $collect; + /** + * @inheritDoc + */ protected function setUp() { $this->collect = Bootstrap::getObjectManager()->create(Collect::class); } + /** + * @return void + */ public function testReport() { $this->collect->getModuleData(); From 5b85e5d8dceeda030cfe44497798de59ef2cb8ec Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 16 Apr 2019 12:31:18 -0500 Subject: [PATCH 524/603] GraphQL-571: [Checkout Coverage] Place order for guest --- .../Model/Resolver/SetGuestEmailOnCart.php | 1 - .../Customer/SetBillingAddressOnCartTest.php | 36 ++++---- .../Customer/SetGuestEmailOnCartTest.php | 35 ++++++-- .../Guest/SetBillingAddressOnCartTest.php | 36 ++++---- .../Quote/Guest/SetGuestEmailOnCartTest.php | 88 ++++++++++++++----- 5 files changed, 128 insertions(+), 68 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php index 29dc0e759242f..202b4f84d70f7 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php @@ -82,7 +82,6 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value return [ 'cart' => [ 'model' => $cart, - 'guest_email' => $guestEmail ], ]; } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php index 553408880baa0..6b15f947a2477 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php @@ -493,6 +493,24 @@ public function testSetBillingAddressWithoutRequiredParameters(string $input, st $this->graphQlMutation($query); } + /** + * @return array + */ + public function dataProviderSetWithoutRequiredParameters(): array + { + return [ + 'missed_billing_address' => [ + 'cart_id: "cart_id_value"', + 'Field SetBillingAddressOnCartInput.billing_address of required type BillingAddressInput!' + . ' was not provided.', + ], + 'missed_cart_id' => [ + 'billing_address: {}', + 'Required parameter "cart_id" is missing' + ] + ]; + } + /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php @@ -536,24 +554,6 @@ public function testSetNewBillingAddressWithRedundantStreetLine() $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } - /** - * @return array - */ - public function dataProviderSetWithoutRequiredParameters(): array - { - return [ - 'missed_billing_address' => [ - 'cart_id: "cart_id_value"', - 'Field SetBillingAddressOnCartInput.billing_address of required type BillingAddressInput!' - . ' was not provided.', - ], - 'missed_cart_id' => [ - 'billing_address: {}', - 'Required parameter "cart_id" is missing' - ] - ]; - } - /** * Verify the all the whitelisted fields for a New Address Object * diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetGuestEmailOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetGuestEmailOnCartTest.php index 4dca82118c1ef..57b734eaa027f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetGuestEmailOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetGuestEmailOnCartTest.php @@ -35,17 +35,36 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * + * @expectedException \Exception + * @expectedExceptionMessage The request is not allowed for logged in customers */ public function testSetGuestEmailOnCartForLoggedInCustomer() { - $reservedOrderId = 'test_order_1'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $email = 'some@user.com'; + + $query = $this->getQuery($maskedQuoteId, $email); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * + * @expectedException \Exception + * @expectedExceptionMessage The request is not allowed for logged in customers + */ + public function testSetGuestEmailOnGuestCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $email = 'some@user.com'; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); - $query = $this->getSetGuestEmailOnCartMutation($maskedQuoteId, $email); - $this->expectExceptionMessage('The request is not allowed for logged in customers'); - $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $query = $this->getQuery($maskedQuoteId, $email); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** @@ -55,12 +74,12 @@ public function testSetGuestEmailOnCartForLoggedInCustomer() * @param string $email * @return string */ - private function getSetGuestEmailOnCartMutation(string $maskedQuoteId, string $email): string + private function getQuery(string $maskedQuoteId, string $email): string { return <<<QUERY mutation { setGuestEmailOnCart(input: { - cart_id:"$maskedQuoteId" + cart_id: "$maskedQuoteId" email: "$email" }) { cart { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php index 5b0e4cfdb6c52..d2d53220f0042 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php @@ -313,6 +313,24 @@ public function testSetBillingAddressWithoutRequiredParameters(string $input, st $this->graphQlMutation($query); } + /** + * @return array + */ + public function dataProviderSetWithoutRequiredParameters(): array + { + return [ + 'missed_billing_address' => [ + 'cart_id: "cart_id_value"', + 'Field SetBillingAddressOnCartInput.billing_address of required type BillingAddressInput!' + . ' was not provided.', + ], + 'missed_cart_id' => [ + 'billing_address: {}', + 'Required parameter "cart_id" is missing' + ] + ]; + } + /** * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php @@ -356,24 +374,6 @@ public function testSetNewBillingAddressRedundantStreetLine() $this->graphQlMutation($query); } - /** - * @return array - */ - public function dataProviderSetWithoutRequiredParameters(): array - { - return [ - 'missed_billing_address' => [ - 'cart_id: "cart_id_value"', - 'Field SetBillingAddressOnCartInput.billing_address of required type BillingAddressInput!' - . ' was not provided.', - ], - 'missed_cart_id' => [ - 'billing_address: {}', - 'Required parameter "cart_id" is missing' - ] - ]; - } - /** * Verify the all the whitelisted fields for a New Address Object * diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetGuestEmailOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetGuestEmailOnCartTest.php index f95679b2eb5e1..5aefa510d7451 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetGuestEmailOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetGuestEmailOnCartTest.php @@ -28,16 +28,15 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Quote/_files/empty_quote.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php */ public function testSetGuestEmailOnCart() { - $reservedOrderId = 'reserved_order_id'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $email = 'some@user.com'; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); - $query = $this->getSetGuestEmailOnCartMutation($maskedQuoteId, $email); - $response = $this->graphQlQuery($query); + $query = $this->getQuery($maskedQuoteId, $email); + $response = $this->graphQlMutation($query); $this->assertArrayHasKey('setGuestEmailOnCart', $response); $this->assertArrayHasKey('cart', $response['setGuestEmailOnCart']); @@ -45,37 +44,80 @@ public function testSetGuestEmailOnCart() } /** - * @magentoApiDataFixture Magento/Quote/_files/empty_quote.php - * @dataProvider incorrectInputDataProvider - * @param string|null $maskedQuoteId + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testSetGuestEmailOnCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $email = 'some@user.com'; + + $query = $this->getQuery($maskedQuoteId, $email); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + $this->graphQlMutation($query); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * + * @dataProvider incorrectEmailDataProvider + * @param string $maskedQuoteId * @param string $email * @param string $exceptionMessage */ - public function testSetGuestEmailOnCartWithIncorrectInputData( - ?string $maskedQuoteId, + public function testSetGuestEmailOnCartWithIncorrectEmail( + string $maskedQuoteId, string $email, string $exceptionMessage ) { - if (null === $maskedQuoteId) { // Generate ID in case if no provided by data provider - $reservedOrderId = 'reserved_order_id'; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); - } + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($maskedQuoteId); - $query = $this->getSetGuestEmailOnCartMutation($maskedQuoteId, $email); + $query = $this->getQuery($maskedQuoteId, $email); $this->expectExceptionMessage($exceptionMessage); - $this->graphQlQuery($query); + $this->graphQlMutation($query); } - public function incorrectInputDataProvider(): array + /** + * @return array + */ + public function incorrectEmailDataProvider(): array { return [ - 'wrong_email' => [null, 'some', 'Invalid email format'], - 'no_email' => [null, '', 'Required parameter "email" is missing'], - 'wrong_quote_id' => ['xxx', 'some@user.com', 'Could not find a cart with ID "xxx"'], - 'no_quote_id' => ['', 'some@user.com', 'Required parameter "cart_id" is missing'] + 'wrong_email' => ['test_quote', 'some', 'Invalid email format'], + 'no_email' => ['test_quote', '', 'Required parameter "email" is missing'], ]; } + /** + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" + */ + public function testSetGuestEmailOnNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $email = 'some@user.com'; + + $query = $this->getQuery($maskedQuoteId, $email); + $this->graphQlMutation($query); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Required parameter "cart_id" is missing + */ + public function testSetGuestEmailWithEmptyCartId() + { + $maskedQuoteId = ''; + $email = 'some@user.com'; + + $query = $this->getQuery($maskedQuoteId, $email); + $this->graphQlMutation($query); + } + /** * Returns GraphQl mutation query for setting email address for a guest * @@ -83,12 +125,12 @@ public function incorrectInputDataProvider(): array * @param string $email * @return string */ - private function getSetGuestEmailOnCartMutation(string $maskedQuoteId, string $email): string + private function getQuery(string $maskedQuoteId, string $email): string { return <<<QUERY mutation { setGuestEmailOnCart(input: { - cart_id:"$maskedQuoteId" + cart_id: "$maskedQuoteId" email: "$email" }) { cart { From c7895084798868169914d9dd046f866979a686e5 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Tue, 16 Apr 2019 13:10:31 -0500 Subject: [PATCH 525/603] MC-15785: Overall storefront improvements --- .../tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.xml index 71115e402880c..0973b968cba95 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.xml @@ -8,7 +8,7 @@ <mapping strict="0"> <fields> <email> - <selector>#customer-email</selector> + <selector>#checkout-customer-email</selector> </email> <firstname /> <lastname /> From ea9abdb22d5530e10e8150c8c30ec91a2e61b89b Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Tue, 16 Apr 2019 13:16:28 -0500 Subject: [PATCH 526/603] MAGETWO-98853: reporting_system_updates table exceptionally large (4gb) --- .../Magento/NewRelicReporting/Model/Module/CollectTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php b/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php index 58759d35337bd..5e5051163cc1f 100644 --- a/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php +++ b/dev/tests/integration/testsuite/Magento/NewRelicReporting/Model/Module/CollectTest.php @@ -10,8 +10,6 @@ /*** * Class CollectTest - * - * @covers Collect */ class CollectTest extends TestCase { From 78349ac9a823386feadccd8f55d05414a24d5831 Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Tue, 16 Apr 2019 13:40:20 -0500 Subject: [PATCH 527/603] MC-15779: Create coupon test functionality for our benchmark --- setup/performance-toolkit/benchmark.jmx | 638 +++++++++++++++++++++++- 1 file changed, 637 insertions(+), 1 deletion(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 696b1964101a5..50fdd7462b254 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -374,6 +374,11 @@ <stringProp name="Argument.value">${__P(graphqlAddSimpleProductToCartPercentage,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> + <elementProp name="graphqlCatalogBrowsingByGuestPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlCatalogBrowsingByGuestPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlCatalogBrowsingByGuestPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> <elementProp name="graphqlCheckoutByGuestPercentage" elementType="Argument"> <stringProp name="Argument.name">graphqlCheckoutByGuestPercentage</stringProp> <stringProp name="Argument.value">${__P(graphqlCheckoutByGuestPercentage,0)}</stringProp> @@ -781,6 +786,7 @@ props.remove("customer_emails_list"); props.remove("categories"); props.remove("cms_pages"); props.remove("cms_blocks"); +props.remove("coupon_codes"); /* This is only used when admin is enabled. */ props.put("activeAdminThread", ""); @@ -2220,6 +2226,59 @@ adminCategoryIdsList.add(vars.get("category_id"));</stringProp> <hashTree/> </hashTree> </hashTree> + + <TestFragmentController guiclass="TestFragmentControllerGui" testclass="TestFragmentController" testname="Extract coupon codes" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/setup/extract_coupon_codes.jmx</stringProp> + </TestFragmentController> + <hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - API Get coupon codes" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="searchCriteria[pageSize]" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">10</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">searchCriteria[pageSize]</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/coupons/search</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <JSR223PostProcessor guiclass="TestBeanGUI" testclass="JSR223PostProcessor" testname="PostProcessor" enabled="true"> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="parameters"/> + <stringProp name="filename"/> + <stringProp name="cacheKey"/> + <stringProp name="script">var data = JSON.parse(prev.getResponseDataAsString()); + +var couponCodes = []; + +for (var i in data.items) { + var coupon = data.items[i]; + couponCodes.push({"coupon_id":coupon.coupon_id, "rule_id":coupon.rule_id, "code": coupon.code}); + } + +props.put("coupon_codes", couponCodes); +</stringProp> + </JSR223PostProcessor> + <hashTree/> + </hashTree> + </hashTree> </hashTree> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - BeanShell Sampler: Validate properties and count users" enabled="true"> @@ -39930,7 +39989,7 @@ vars.putObject("category", categories[number]); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"query productSearch($inputText: String!, $categoryId: String) {\n products(search: $inputText, filter: { category_id: { eq: $categoryId } }) {\n items {\n id\n name\n small_image {\n label\n url\n }\n url_key\n price {\n regularPrice {\n amount {\n value\n currency\n }\n }\n }\n }\n total_count\n filters {\n name\n filter_items_count\n request_var\n filter_items {\n label\n value_string\n }\n }\n }\n}","variables":{"inputText":"Product","categoryId":"${category_id}"},"operationName":"productSearch"}</stringProp> + <stringProp name="Argument.value">{"query":"query productSearch($inputText: String!, $categoryId: String) {\n products(\n pageSize:12\n search: $inputText, filter: { category_id: { eq: $categoryId } }) {\n items {\n id\n name\n small_image {\n label\n url\n }\n url_key\n price {\n regularPrice {\n amount {\n value\n currency\n }\n }\n }\n }\n total_count\n filters {\n name\n filter_items_count\n request_var\n filter_items {\n label\n value_string\n }\n }\n }\n}","variables":{"inputText":"Product","categoryId":"${category_id}"},"operationName":"productSearch"}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42662,6 +42721,583 @@ vars.put("product_sku", product.get("sku")); </hashTree> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Catalog Browsing By Guest" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlCatalogBrowsingByGuestPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "GraphQL Catalog Browsing By Guest"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <JSR223Sampler guiclass="TestBeanGUI" testclass="JSR223Sampler" testname="SetUp - Prepare Category Data" enabled="true"> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="parameters"/> + <stringProp name="filename"/> + <stringProp name="cacheKey"/> + <stringProp name="script">random = vars.getObject("randomIntGenerator"); + +var categories = props.get("categories"); +number = random.nextInt(categories.length); + +vars.put("category_url_key", categories[number].url_key); +vars.put("category_name", categories[number].name); +vars.put("category_id", categories[number].id); +vars.putObject("category", categories[number]); + </stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/extract_category_setup.jmx</stringProp></JSR223Sampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Category List by category_id" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"> + {"query":"query categoryList($id: Int!) {\n category(id: $id) {\n id\n children {\n id\n name\n url_key\n url_path\n children_count\n path\n image\n productImagePreview: products(pageSize: 1) {\n items {\n small_image {\n label\n url\n }\n }\n }\n }\n }\n}","variables":{"id":${category_id}},"operationName":"categoryList"} + </stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_category_list_by_category_id.jmx</stringProp></HTTPSamplerProxy> + <hashTree> + <JSR223Assertion guiclass="TestBeanGUI" testclass="JSR223Assertion" testname="Assert found categories" enabled="true"> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="parameters"/> + <stringProp name="filename"/> + <stringProp name="cacheKey"/> + <stringProp name="script">var category = vars.getObject("category"); +var response = JSON.parse(prev.getResponseDataAsString()); + +assertCategoryId(category, response); +assertCategoryChildren(category, response); + +function assertCategoryId(category, response) { + if (response.data == undefined || response.data.category == undefined || response.data.category.id != category.id) { + AssertionResult.setFailureMessage("Cannot find category with id \"" + category.id + "\""); + AssertionResult.setFailure(true); + } +} + +function assertCategoryChildren(category, response) { + foundCategory = response.data && response.data.category ? response.data.category : null; + if (foundCategory) { + var childrenFound = foundCategory.children.map(function (c) {return parseInt(c.id)}); + var children = category.children.map(function (c) {return parseInt(c)}); + if (JSON.stringify(children.sort()) != JSON.stringify(childrenFound.sort())) { + AssertionResult.setFailureMessage("Cannot math children categories \"" + JSON.stringify(children) + "\" for to found one: \"" + JSON.stringify(childrenFound) + "\""); + AssertionResult.setFailure(true); + } + } + +} + +</stringProp> + </JSR223Assertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Navigation Menu by category_id" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query navigationMenu($id: Int!) {\n category(id: $id) {\n id\n name\n product_count\n path\n children {\n id\n name\n position\n level\n url_key\n url_path\n product_count\n children_count\n path\n productImagePreview: products(pageSize: 1) {\n items {\n small_image {\n label\n url\n }\n }\n }\n }\n }\n}","variables":{"id":${category_id}},"operationName":"navigationMenu"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_navigation_menu_by_category_id.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"id":${category_id},"name":"${category_name}","product_count"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Product Search by text and category_id" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productSearch($inputText: String!, $categoryId: String) {\n products(\n pageSize:12\n search: $inputText, filter: { category_id: { eq: $categoryId } }) {\n items {\n id\n name\n small_image {\n label\n url\n }\n url_key\n price {\n regularPrice {\n amount {\n value\n currency\n }\n }\n }\n }\n total_count\n filters {\n name\n filter_items_count\n request_var\n filter_items {\n label\n value_string\n }\n }\n }\n}","variables":{"inputText":"Product","categoryId":"${category_id}"},"operationName":"productSearch"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_product_search_by_text_and_category_id.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract total_count" enabled="true"> + <stringProp name="VAR">graphql_search_products_query_total_count</stringProp> + <stringProp name="JSONPATH">$.data.products.total_count</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <BeanShellAssertion guiclass="BeanShellAssertionGui" testclass="BeanShellAssertion" testname="Assert total count > 0" enabled="true"> + <stringProp name="BeanShellAssertion.query">String totalCount=vars.get("graphql_search_products_query_total_count"); + +if (totalCount == null) { + Failure = true; + FailureMessage = "Not Expected \"totalCount\" to be null"; +} else { + if (Integer.parseInt(totalCount) < 1) { + Failure = true; + FailureMessage = "Expected \"totalCount\" to be greater than zero, Actual: " + totalCount; + } else { + Failure = false; + } +} + + +</stringProp> + <stringProp name="BeanShellAssertion.filename"/> + <stringProp name="BeanShellAssertion.parameters"/> + <boolProp name="BeanShellAssertion.resetInterpreter">false</boolProp> + </BeanShellAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Url Info by url_key" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"> + {"query":"query resolveUrl($urlKey: String!) {\n urlResolver(url: $urlKey) {\n type\n id\n }\n}","variables":{"urlKey":"${category_url_key}${url_suffix}"},"operationName":"resolveUrl"} + </stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_url_info_by_url_key.jmx</stringProp></HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1062388959">{"type":"CATEGORY","id":${category_id}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get List of Products by category_id" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query category($id: Int!, $currentPage: Int, $pageSize: Int) {\n category(id: $id) {\n product_count\n description\n url_key\n name\n id\n breadcrumbs {\n category_name\n category_url_key\n __typename\n }\n products(pageSize: $pageSize, currentPage: $currentPage) {\n total_count\n items {\n id\n name\n # small_image\n # short_description\n url_key\n special_price\n special_from_date\n special_to_date\n price {\n regularPrice {\n amount {\n value\n currency\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n}\n","variables":{"id":${category_id},"currentPage":1,"pageSize":12},"operationName":"category"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_list_of_products_by_category_id.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"name":"${category_name}","id":${category_id},</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("configurable_products_list").size()); +product = props.get("configurable_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by product_url_key" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productDetail($urlKey: String, $onServer: Boolean!) {\n productDetail: products(filter: { url_key: { eq: $urlKey } }) {\n items {\n sku\n name\n price {\n regularPrice {\n amount {\n currency\n value\n }\n }\n }\n description {html}\n media_gallery_entries {\n label\n position\n disabled\n file\n }\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n # Yes, Products have `meta_keyword` and\n # everything else has `meta_keywords`.\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"urlKey":"${product_url_key}","onServer":false},"operationName":"productDetail"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_product_url_key.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("simple_products_list").size()); +product = props.get("simple_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Simple Product Details by name" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productDetail($name: String, $onServer: Boolean!) {\n productDetail: products(filter: { name: { eq: $name } }) {\n items {\n sku\n name\n price {\n regularPrice {\n amount {\n currency\n value\n }\n }\n }\n description {html}\n media_gallery_entries {\n label\n position\n disabled\n file\n }\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n # Yes, Products have `meta_keyword` and\n # everything else has `meta_keywords`.\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetail"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_simple_product_details_by_name.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Simple Product Details by product_url_key" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productDetail($urlKey: String, $onServer: Boolean!) {\n productDetail: products(filter: { url_key: { eq: $urlKey } }) {\n items {\n sku\n name\n price {\n regularPrice {\n amount {\n currency\n value\n }\n }\n }\n description {html}\n media_gallery_entries {\n label\n position\n disabled\n file\n }\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n # Yes, Products have `meta_keyword` and\n # everything else has `meta_keywords`.\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"urlKey":"${product_url_key}","onServer":false},"operationName":"productDetail"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_simple_product_details_by_product_url_key.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <JSR223Sampler guiclass="TestBeanGUI" testclass="JSR223Sampler" testname="SetUp - Prepare CMS Page" enabled="true"> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="parameters"/> + <stringProp name="filename"/> + <stringProp name="cacheKey"/> + <stringProp name="script">random = vars.getObject("randomIntGenerator"); + +var cmsPages = props.get("cms_pages"); +var number = random.nextInt(cmsPages.length); + +vars.put("cms_page_id", cmsPages[number].id); + </stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/setup/prepare_cms_page.jmx</stringProp></JSR223Sampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cms Page by id" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"> + {"query":"query getCmsPage($id: Int!, $onServer: Boolean!) {\n cmsPage(id: $id) {\n url_key\n content\n content_heading\n title\n page_layout\n meta_title @include(if: $onServer)\n meta_keywords @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n}","variables":{"id":${cms_page_id},"onServer":false},"operationName":"getCmsPage"} + </stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_get_cms_page_by_id.jmx</stringProp></HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion.JSONPathAssertion guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion.gui.JSONPathAssertionGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion.JSONPathAssertion" testname="jp@gc - JSON Path Assertion" enabled="true"> + <stringProp name="JSON_PATH">$.data.cmsPage.url_key</stringProp> + <stringProp name="EXPECTED_VALUE">${cms_page_id}</stringProp> + <boolProp name="JSONVALIDATION">false</boolProp> + <boolProp name="EXPECT_NULL">false</boolProp> + <boolProp name="INVERT">false</boolProp> + <boolProp name="ISREGEX">false</boolProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion.JSONPathAssertion> + <hashTree/> + </hashTree> + </hashTree> + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Checkout By Guest" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> From 737ee93c49d1dbeabab36185ea51d918d3c01dad Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Tue, 16 Apr 2019 14:02:51 -0500 Subject: [PATCH 528/603] MC-15779: Create coupon test functionality for our benchmark --- setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php b/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php index 31e5ab9ebd575..d68d936aa3af6 100644 --- a/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php +++ b/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php @@ -20,7 +20,7 @@ class CouponCodesFixture extends Fixture /** * @var int */ - protected $priority = 130; + protected $priority = 129; /** * @var int From f88b9e339553dda75d2119cb412119912e760ed7 Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Tue, 16 Apr 2019 14:40:59 -0500 Subject: [PATCH 529/603] MC-15779: Create coupon test functionality for our benchmark --- .../src/Magento/Setup/Fixtures/CouponCodesFixture.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php b/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php index d68d936aa3af6..e60a2c9f30765 100644 --- a/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php +++ b/setup/src/Magento/Setup/Fixtures/CouponCodesFixture.php @@ -57,7 +57,8 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc + * * @SuppressWarnings(PHPMD) */ public function execute() @@ -101,9 +102,12 @@ public function execute() } /** + * Generate Coupon Codes + * * @param \Magento\SalesRule\Model\RuleFactory $ruleFactory * @param \Magento\SalesRule\Model\CouponFactory $couponCodeFactory * @param array $categoriesArray + * * @return void */ public function generateCouponCodes($ruleFactory, $couponCodeFactory, $categoriesArray) @@ -145,7 +149,7 @@ public function generateCouponCodes($ruleFactory, $couponCodeFactory, $categorie } /** - * {@inheritdoc} + * @inheritdoc */ public function getActionTitle() { @@ -153,7 +157,7 @@ public function getActionTitle() } /** - * {@inheritdoc} + * @inheritdoc */ public function introduceParamLabels() { From 58fa5d4b28d0622321b59924cd0fe21aff06c8b9 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 16 Apr 2019 14:59:28 -0500 Subject: [PATCH 530/603] GraphQL-571: [Checkout Coverage] Place order for guest --- .../{GuestEmail.php => CartEmail.php} | 2 +- .../Magento/QuoteGraphQl/etc/schema.graphqls | 2 +- .../Quote/Customer/GetCartEmailTest.php | 125 ++++++++++++++++++ .../Quote/Guest/CartGuestEmailTest.php | 52 -------- .../GraphQl/Quote/Guest/GetCartEmailTest.php | 88 ++++++++++++ .../Quote/_files/guest/set_guest_email.php | 2 +- 6 files changed, 216 insertions(+), 55 deletions(-) rename app/code/Magento/QuoteGraphQl/Model/Resolver/{GuestEmail.php => CartEmail.php} (96%) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartEmailTest.php delete mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartGuestEmailTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartEmailTest.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/GuestEmail.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartEmail.php similarity index 96% rename from app/code/Magento/QuoteGraphQl/Model/Resolver/GuestEmail.php rename to app/code/Magento/QuoteGraphQl/Model/Resolver/CartEmail.php index 76493c4cebe55..8d0cb114d8315 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/GuestEmail.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartEmail.php @@ -17,7 +17,7 @@ /** * @inheritdoc */ -class GuestEmail implements ResolverInterface +class CartEmail implements ResolverInterface { /** * @var GetCartForUser diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 22a5bb6cce392..711e6cbc7f5f6 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -175,7 +175,7 @@ type PlaceOrderOutput { type Cart { items: [CartItemInterface] @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartItems") applied_coupon: AppliedCoupon @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\AppliedCoupon") - guest_email: String @resolver (class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\GuestEmail") + email: String @resolver (class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartEmail") shipping_addresses: [CartAddress]! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddresses") billing_address: CartAddress! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\BillingAddress") available_payment_methods: [AvailablePaymentMethod] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AvailablePaymentMethods") @doc(description: "Available payment methods") diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartEmailTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartEmailTest.php new file mode 100644 index 0000000000000..951fe08db5e3d --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartEmailTest.php @@ -0,0 +1,125 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for getting email from cart + */ +class GetCartEmailTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testGetCartEmail() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + + $this->assertArrayHasKey('cart', $response); + $this->assertArrayHasKey('email', $response['cart']); + $this->assertEquals('customer@example.com', $response['cart']['email']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" + */ + public function testGetCartEmailFromNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); + + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/set_guest_email.php + */ + public function testGetEmailFromGuestCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"{$maskedQuoteId}\"" + ); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testGetEmailFromAnotherCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"{$maskedQuoteId}\"" + ); + $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer3@search.example.com')); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id:"$maskedQuoteId") { + email + } +} +QUERY; + } + + /** + * @param string $username + * @param string $password + * @return array + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartGuestEmailTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartGuestEmailTest.php deleted file mode 100644 index 751029e6b87a3..0000000000000 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartGuestEmailTest.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\GraphQl\Quote\Guest; - -use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\TestFramework\TestCase\GraphQlAbstract; - -/** - * Test for getting guest email from cart - */ -class CartGuestEmailTest extends GraphQlAbstract -{ - /** - * @var GetMaskedQuoteIdByReservedOrderId - */ - private $getMaskedQuoteIdByReservedOrderId; - - protected function setUp() - { - $objectManager = Bootstrap::getObjectManager(); - $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php - */ - public function testGetCartGuestEmail() - { - $email = 'store@example.com'; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute( - 'test_order_with_virtual_product_without_address' - ); - - $query = <<<QUERY -{ - cart(cart_id:"$maskedQuoteId") { - guest_email - } -} -QUERY; - - $response = $this->graphQlQuery($query); - $this->assertArrayHasKey('cart', $response); - $this->assertEquals($email, $response['cart']['guest_email']); - } -} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartEmailTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartEmailTest.php new file mode 100644 index 0000000000000..8c6ecd075049f --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartEmailTest.php @@ -0,0 +1,88 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for getting email from cart + */ +class GetCartEmailTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/set_guest_email.php + */ + public function testGetCartEmail() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query); + + $this->assertArrayHasKey('cart', $response); + $this->assertArrayHasKey('email', $response['cart']); + $this->assertEquals('guest@example.com', $response['cart']['email']); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" + */ + public function testGetCartEmailFromNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); + + $this->graphQlQuery($query); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testGetCartEmailFromCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"{$maskedQuoteId}\"" + ); + $this->graphQlQuery($query); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id:"$maskedQuoteId") { + email + } +} +QUERY; + } +} diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/guest/set_guest_email.php b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/guest/set_guest_email.php index 4e214f4310044..c8084b2552395 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/guest/set_guest_email.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/guest/set_guest_email.php @@ -20,5 +20,5 @@ $quote = $quoteFactory->create(); $quoteResource->load($quote, 'test_quote', 'reserved_order_id'); -$quote->setCustomerEmail('customer@example.com'); +$quote->setCustomerEmail('guest@example.com'); $cartRepository->save($quote); From 44b99de26f3a8c9afbca458e3f7bf9a313cee56b Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 16 Apr 2019 15:11:01 -0500 Subject: [PATCH 531/603] GraphQL-571: [Checkout Coverage] Place order for guest --- .../Model/Resolver/SetGuestEmailOnCart.php | 17 ++++++++++++----- .../Quote/Customer/SetGuestEmailOnCartTest.php | 2 +- .../Quote/Guest/SetGuestEmailOnCartTest.php | 12 +++++------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php index 202b4f84d70f7..d621057348b54 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php @@ -32,16 +32,24 @@ class SetGuestEmailOnCart implements ResolverInterface */ private $getCartForUser; + /** + * @var EmailAddressValidator + */ + private $emailValidator; + /** * @param GetCartForUser $getCartForUser * @param CartRepositoryInterface $cartRepository + * @param EmailAddressValidator $emailValidator */ public function __construct( GetCartForUser $getCartForUser, - CartRepositoryInterface $cartRepository + CartRepositoryInterface $cartRepository, + EmailAddressValidator $emailValidator ) { $this->getCartForUser = $getCartForUser; $this->cartRepository = $cartRepository; + $this->emailValidator = $emailValidator; } /** @@ -58,11 +66,10 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value throw new GraphQlInputException(__('Required parameter "email" is missing')); } - $guestEmail = $args['input']['email']; - - if (!\Zend_Validate::is($guestEmail, EmailAddressValidator::class)) { + if (false === $this->emailValidator->isValid($args['input']['email'])) { throw new GraphQlInputException(__('Invalid email format')); } + $email = $args['input']['email']; $currentUserId = $context->getUserId(); @@ -71,7 +78,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } $cart = $this->getCartForUser->execute($maskedCartId, $currentUserId); - $cart->setCustomerEmail($guestEmail); + $cart->setCustomerEmail($email); try { $this->cartRepository->save($cart); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetGuestEmailOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetGuestEmailOnCartTest.php index 57b734eaa027f..a4a84c2f8c740 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetGuestEmailOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetGuestEmailOnCartTest.php @@ -83,7 +83,7 @@ private function getQuery(string $maskedQuoteId, string $email): string email: "$email" }) { cart { - guest_email + email } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetGuestEmailOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetGuestEmailOnCartTest.php index 5aefa510d7451..b877dccdeba37 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetGuestEmailOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetGuestEmailOnCartTest.php @@ -40,7 +40,7 @@ public function testSetGuestEmailOnCart() $this->assertArrayHasKey('setGuestEmailOnCart', $response); $this->assertArrayHasKey('cart', $response['setGuestEmailOnCart']); - $this->assertEquals($email, $response['setGuestEmailOnCart']['cart']['guest_email']); + $this->assertEquals($email, $response['setGuestEmailOnCart']['cart']['email']); } /** @@ -65,16 +65,14 @@ public function testSetGuestEmailOnCustomerCart() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * * @dataProvider incorrectEmailDataProvider - * @param string $maskedQuoteId * @param string $email * @param string $exceptionMessage */ public function testSetGuestEmailOnCartWithIncorrectEmail( - string $maskedQuoteId, string $email, string $exceptionMessage ) { - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($maskedQuoteId); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $email); $this->expectExceptionMessage($exceptionMessage); @@ -87,8 +85,8 @@ public function testSetGuestEmailOnCartWithIncorrectEmail( public function incorrectEmailDataProvider(): array { return [ - 'wrong_email' => ['test_quote', 'some', 'Invalid email format'], - 'no_email' => ['test_quote', '', 'Required parameter "email" is missing'], + 'wrong_email' => ['some', 'Invalid email format'], + 'no_email' => ['', 'Required parameter "email" is missing'], ]; } @@ -134,7 +132,7 @@ private function getQuery(string $maskedQuoteId, string $email): string email: "$email" }) { cart { - guest_email + email } } } From f41b4fb16e16d847f925baaa0878987157bb7279 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Tue, 16 Apr 2019 15:45:29 -0500 Subject: [PATCH 532/603] MC-15785: Overall storefront improvements --- .../tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php index 0bf9b37c75e12..1013404f42df1 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php @@ -102,7 +102,7 @@ class Shipping extends Form * * @var string */ - private $emailError = '#customer-email-error'; + private $emailError = '#checkout-customer-email-error'; /** * Get email error. From b67192ad4e211f9eaea156a4a71b5fb174fe3040 Mon Sep 17 00:00:00 2001 From: "Leandro F. L" <lfluvisotto@gmail.com> Date: Tue, 16 Apr 2019 18:53:41 -0300 Subject: [PATCH 533/603] Remove all marketing get params on Varnish to minimize the cache objects (added bronto parameter) --- app/code/Magento/PageCache/etc/varnish4.vcl | 4 ++-- app/code/Magento/PageCache/etc/varnish5.vcl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/PageCache/etc/varnish4.vcl b/app/code/Magento/PageCache/etc/varnish4.vcl index 198b2f6796e69..801e6cb475d8a 100644 --- a/app/code/Magento/PageCache/etc/varnish4.vcl +++ b/app/code/Magento/PageCache/etc/varnish4.vcl @@ -92,8 +92,8 @@ sub vcl_recv { } # Remove all marketing get parameters to minimize the cache objects - if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=") { - set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); + if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=") { + set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); set req.url = regsub(req.url, "[?|&]+$", ""); } diff --git a/app/code/Magento/PageCache/etc/varnish5.vcl b/app/code/Magento/PageCache/etc/varnish5.vcl index eac724ea7d0a5..76c5ffee5f14f 100644 --- a/app/code/Magento/PageCache/etc/varnish5.vcl +++ b/app/code/Magento/PageCache/etc/varnish5.vcl @@ -93,8 +93,8 @@ sub vcl_recv { } # Remove all marketing get parameters to minimize the cache objects - if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=") { - set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); + if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=") { + set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); set req.url = regsub(req.url, "[?|&]+$", ""); } From 4fb0be0e00ef6fca6e94689d3b176097e76b82fb Mon Sep 17 00:00:00 2001 From: Ansari <ziyaurrahman@krishtechnolabs.com> Date: Wed, 17 Apr 2019 11:33:07 +0530 Subject: [PATCH 534/603] Qty box visibility issue in whishlist when product is out of stock --- .../Wishlist/view/frontend/templates/item/column/cart.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml index 848c6a76393f8..c85f41bbf0775 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml @@ -18,7 +18,7 @@ $allowedQty = $block->getMinMaxQty(); <?php endforeach;?> <div class="box-tocart"> <fieldset class="fieldset"> - <?php if ($item->canHaveQty() && $product->isVisibleInSiteVisibility()): ?> + <?php if ($item->canHaveQty() && $product->isVisibleInSiteVisibility() && $product->isSaleable()): ?> <div class="field qty"> <label class="label" for="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]"><span><?= $block->escapeHtml(__('Qty')) ?></span></label> <div class="control"> From e340978f1ef25bb39d5e03939ddad30b0c927eab Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Wed, 17 Apr 2019 11:37:02 +0300 Subject: [PATCH 535/603] Fix static test. --- .../Magento/Config/Model/Config/Backend/Admin/Usecustom.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php b/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php index d12569eebe5b2..f5d568f2f36be 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php +++ b/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php @@ -10,6 +10,8 @@ namespace Magento\Config\Model\Config\Backend\Admin; /** + * Process custom admin url during configuration value save process. + * * @api * @since 100.0.2 */ From 4d37719fcd446584aca5c1f77c56e24870c77d9f Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 16 Apr 2019 10:41:09 +0300 Subject: [PATCH 536/603] magento/magento2#21756: Static test fix. --- .../View/Asset/MergeStrategy/Direct.php | 19 +++++++++-------- .../Unit/Asset/MergeStrategy/DirectTest.php | 21 ++++++++++++------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php b/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php index e6ff58efe071a..315c3ee204864 100644 --- a/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php +++ b/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php @@ -6,6 +6,8 @@ namespace Magento\Framework\View\Asset\MergeStrategy; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Math\Random; use Magento\Framework\View\Asset; /** @@ -31,27 +33,27 @@ class Direct implements \Magento\Framework\View\Asset\MergeStrategyInterface private $cssUrlResolver; /** - * @var \Magento\Framework\Math\Random + * @var Random */ private $mathRandom; /** * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\View\Url\CssResolver $cssUrlResolver - * @param \Magento\Framework\Math\Random|null $mathRandom + * @param Random|null $mathRandom */ public function __construct( \Magento\Framework\Filesystem $filesystem, \Magento\Framework\View\Url\CssResolver $cssUrlResolver, - \Magento\Framework\Math\Random $mathRandom = null + Random $mathRandom = null ) { $this->filesystem = $filesystem; $this->cssUrlResolver = $cssUrlResolver; - $this->mathRandom = $mathRandom ?: \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Framework\Math\Random::class);; + $this->mathRandom = $mathRandom ?: ObjectManager::getInstance()->get(Random::class); } /** - * {@inheritdoc} + * @inheritdoc */ public function merge(array $assetsToMerge, Asset\LocalInterface $resultAsset) { @@ -67,10 +69,9 @@ public function merge(array $assetsToMerge, Asset\LocalInterface $resultAsset) /** * Merge files together and modify content if needed * - * @param \Magento\Framework\View\Asset\MergeableInterface[] $assetsToMerge - * @param \Magento\ Framework\View\Asset\LocalInterface $resultAsset - * @return string - * @throws \Magento\Framework\Exception\LocalizedException + * @param array $assetsToMerge + * @param Asset\LocalInterface $resultAsset + * @return array|string */ private function composeMergedContent(array $assetsToMerge, Asset\LocalInterface $resultAsset) { diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/DirectTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/DirectTest.php index 19b17b4b52596..c23f13745c79f 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/DirectTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/DirectTest.php @@ -5,11 +5,13 @@ */ namespace Magento\Framework\View\Test\Unit\Asset\MergeStrategy; -use Magento\Framework\Filesystem\Directory\WriteInterface; -use \Magento\Framework\View\Asset\MergeStrategy\Direct; - use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Filesystem\Directory\WriteInterface; +use Magento\Framework\View\Asset\MergeStrategy\Direct; +/** + * Test for Magento\Framework\View\Asset\MergeStrategy\Direct. + */ class DirectTest extends \PHPUnit\Framework\TestCase { /** @@ -69,7 +71,8 @@ public function testMergeNoAssets() ->method('getUniqueHash') ->willReturn($uniqId); $this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result' . $uniqId, ''); - $this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); + $this->tmpDir->expects($this->once())->method('renameFile') + ->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); $this->object->merge([], $this->resultAsset); } @@ -83,7 +86,8 @@ public function testMergeGeneric() ->method('getUniqueHash') ->willReturn($uniqId); $this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result' . $uniqId, 'onetwo'); - $this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); + $this->tmpDir->expects($this->once())->method('renameFile') + ->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); $this->object->merge($assets, $this->resultAsset); } @@ -92,7 +96,7 @@ public function testMergeCss() $uniqId = '_f929c374767e00712449660ea673f2f5'; $this->resultAsset->expects($this->exactly(3)) ->method('getPath') - ->will($this->returnValue('foo/result')); + ->willReturn('foo/result'); $this->resultAsset->expects($this->any())->method('getContentType')->will($this->returnValue('css')); $assets = $this->prepareAssetsToMerge(['one', 'two']); $this->cssUrlResolver->expects($this->exactly(2)) @@ -101,13 +105,14 @@ public function testMergeCss() $this->cssUrlResolver->expects($this->once()) ->method('aggregateImportDirectives') ->with('12') - ->will($this->returnValue('1020')); + ->willReturn('1020'); $this->mathRandomMock->expects($this->once()) ->method('getUniqueHash') ->willReturn($uniqId); $this->staticDir->expects($this->never())->method('writeFile'); $this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result' . $uniqId, '1020'); - $this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); + $this->tmpDir->expects($this->once())->method('renameFile') + ->with('foo/result' . $uniqId, 'foo/result', $this->staticDir); $this->object->merge($assets, $this->resultAsset); } From 6beb286340905840df531d37f9cc18b71ab9aeb4 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Wed, 17 Apr 2019 12:30:17 +0300 Subject: [PATCH 537/603] magento/magento2#18336: Static test fix. --- lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php b/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php index fa58bdb5a5ebb..4d84be1ba4fc1 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php +++ b/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Framework\Config\Test\Unit; +/** + * Test for \Magento\Framework\Config\Dom class. + */ class DomTest extends \PHPUnit\Framework\TestCase { /** From 7ba832e243036b43ee15dab6f8a5183a31dba7ae Mon Sep 17 00:00:00 2001 From: Nikita Fomin <fmnnkt@gmail.com> Date: Wed, 17 Apr 2019 13:19:17 +0300 Subject: [PATCH 538/603] MC-11945: Update Configurable Product --- .../Test/TestCase/UpdateConfigurableProductEntityTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/UpdateConfigurableProductEntityTest.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/UpdateConfigurableProductEntityTest.php index c7d66781738b7..bb88bc854f756 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/UpdateConfigurableProductEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/UpdateConfigurableProductEntityTest.php @@ -32,7 +32,6 @@ class UpdateConfigurableProductEntityTest extends Scenario { /* tags */ const MVP = 'yes'; - const TO_MAINTAIN = 'yes'; /* end tags */ /** From eea6126c03b6bb807569b73b7141d74257883729 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Wed, 17 Apr 2019 15:37:47 +0300 Subject: [PATCH 539/603] Fix static tests. --- .../Magento/Eav/Model/Entity/Collection/AbstractCollection.php | 1 - .../Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php | 1 + lib/internal/Magento/Framework/Data/Collection.php | 2 ++ 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index 247ee2d5423cd..51bb45c61a585 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -1719,5 +1719,4 @@ public function removeAllFieldsFromSelect() { return $this->removeAttributeToSelect(); } - } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php index 396d3b60e4f20..3ade17d90fe99 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/CartTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Block\Adminhtml\Edit\Tab\View; use Magento\Customer\Controller\RegistryConstants; diff --git a/lib/internal/Magento/Framework/Data/Collection.php b/lib/internal/Magento/Framework/Data/Collection.php index 306737f4b5877..e0781a25de146 100644 --- a/lib/internal/Magento/Framework/Data/Collection.php +++ b/lib/internal/Magento/Framework/Data/Collection.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Data; use Magento\Framework\Data\Collection\EntityFactoryInterface; @@ -401,6 +402,7 @@ public function addItem(\Magento\Framework\DataObject $item) if ($itemId !== null) { if (isset($this->_items[$itemId])) { + //phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception( 'Item (' . get_class($item) . ') with the same ID "' . $item->getId() . '" already exists.' ); From 86c84a403d904b8fd503ed4738c694f61b64ccea Mon Sep 17 00:00:00 2001 From: Rafael Kassner <kassner@gmail.com> Date: Tue, 16 Apr 2019 13:10:09 +0200 Subject: [PATCH 540/603] Fix buttonId for credit memo button on admin invoice view --- app/code/Magento/Sales/Block/Adminhtml/Order/Invoice/View.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Invoice/View.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Invoice/View.php index fd6e5f403f2de..074aa99a5e791 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Invoice/View.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Invoice/View.php @@ -113,8 +113,8 @@ protected function _construct() $orderPayment->canRefund() && !$this->getInvoice()->getIsUsedForRefund() ) { $this->buttonList->add( - 'capture', - [ // capture? + 'credit-memo', + [ 'label' => __('Credit Memo'), 'class' => 'credit-memo', 'onclick' => 'setLocation(\'' . $this->getCreditMemoUrl() . '\')' From 4fcf7ed65838eb060e4a18f674d5e0498b02103b Mon Sep 17 00:00:00 2001 From: Volodymyr Vygovskyi <v.vygovskyi@atwix.com> Date: Wed, 17 Apr 2019 16:02:16 +0300 Subject: [PATCH 541/603] Added test coverage for Adding simple product to cart functionality --- .../Customer/AddSimpleProductToCartTest.php | 177 ++++++++++++++++++ .../Guest/AddSimpleProductToCartTest.php | 48 ++++- 2 files changed, 219 insertions(+), 6 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php new file mode 100644 index 0000000000000..0ff96c03e0990 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php @@ -0,0 +1,177 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\Framework\Exception\AuthenticationException; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test adding simple product to Cart + */ +class AddSimpleProductToCartTest extends GraphQlAbstract +{ + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testAddSimpleProductToCart() + { + $sku = 'simple_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); + self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + */ + public function testAddProductToNonExistentCart() + { + $sku = 'simple_product'; + $qty = 2; + $nonExistentMaskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($nonExistentMaskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not find a cart with ID \"$nonExistentMaskedQuoteId\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testNonExistentProductToCart() + { + $sku = 'simple_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not find a product with SKU \"simple_product\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + */ + public function testAddSimpleProductToGuestCart() + { + $sku = 'simple_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + */ + public function testAddSimpleProductToAnotherCustomerCart() + { + $sku = 'simple_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer2@search.example.com')); + } + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + { + return <<<QUERY +mutation { + addSimpleProductsToCart(input: { + cart_id: "{$maskedQuoteId}", + cartItems: [ + { + data: { + qty: $qty + sku: "$sku" + } + } + ] + }) { + cart { + items { + id + qty + product { + sku + } + } + } + } +} +QUERY; + } + + /** + * Retrieve customer authorization headers + * + * @param string $username + * @param string $password + * @return array + * @throws AuthenticationException + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php index 25221b628e7fb..f4345c9ab4826 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php @@ -31,14 +31,14 @@ protected function setUp() } /** - * @magentoApiDataFixture Magento/Catalog/_files/products.php - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php */ public function testAddSimpleProductToCart() { - $sku = 'simple'; + $sku = 'simple_product'; $qty = 2; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId, $sku, $qty); $response = $this->graphQlMutation($query); @@ -49,14 +49,14 @@ public function testAddSimpleProductToCart() } /** - * @magentoApiDataFixture Magento/Catalog/_files/products.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * * @expectedException \Exception * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ public function testAddProductToNonExistentCart() { - $sku = 'simple'; + $sku = 'simple_product'; $qty = 1; $maskedQuoteId = 'non_existent_masked_id'; @@ -64,6 +64,42 @@ public function testAddProductToNonExistentCart() $this->graphQlMutation($query); } + /** + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + */ + public function testNonExistentProductToCart() + { + $sku = 'simple_product'; + $qty = 1; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not find a product with SKU \"simple_product\"" + ); + + $this->graphQlMutation($query); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testAddSimpleProductToCustomerCart() + { + $sku = 'simple_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlMutation($query); + } + /** * @param string $maskedQuoteId * @param string $sku From e2854aadc76f56d5ac21e2f8ab648c3f34e3a2af Mon Sep 17 00:00:00 2001 From: Volodymyr Vygovskyi <v.vygovskyi@atwix.com> Date: Wed, 17 Apr 2019 17:10:49 +0300 Subject: [PATCH 542/603] Added test coverage for Add virtual product to cart functionality --- .../Customer/AddVirtualProductToCartTest.php | 177 ++++++++++++++++++ .../Guest/AddVirtualProductToCartTest.php | 139 ++++++++++++++ .../Catalog/_files/virtual_product.php | 45 +++++ .../_files/virtual_product_rollback.php | 31 +++ 4 files changed, 392 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product_rollback.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php new file mode 100644 index 0000000000000..f2beef7aa93c8 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php @@ -0,0 +1,177 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\Framework\Exception\AuthenticationException; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test adding virtual product to Cart + */ +class AddVirtualProductToCartTest extends GraphQlAbstract +{ + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testAddVirtualProductToCart() + { + $sku = 'virtual_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('cart', $response['addVirtualProductsToCart']); + self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($sku, $response['addVirtualProductsToCart']['cart']['items'][0]['product']['sku']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + */ + public function testAddVirtualToNonExistentCart() + { + $sku = 'virtual_product'; + $qty = 2; + $nonExistentMaskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($nonExistentMaskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not find a cart with ID \"$nonExistentMaskedQuoteId\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testNonExistentProductToCart() + { + $sku = 'virtual_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not find a product with SKU \"virtual_product\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + */ + public function testAddVirtualProductToGuestCart() + { + $sku = 'virtual_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + */ + public function testAddVirtualProductToAnotherCustomerCart() + { + $sku = 'virtual_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer2@search.example.com')); + } + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + { + return <<<QUERY +mutation { + addVirtualProductsToCart(input: { + cart_id: "{$maskedQuoteId}", + cartItems: [ + { + data: { + qty: $qty + sku: "$sku" + } + } + ] + }) { + cart { + items { + id + qty + product { + sku + } + } + } + } +} +QUERY; + } + + /** + * Retrieve customer authorization headers + * + * @param string $username + * @param string $password + * @return array + * @throws AuthenticationException + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php new file mode 100644 index 0000000000000..20d7ee031a044 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php @@ -0,0 +1,139 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Add virtual product to cart testcases + */ +class AddVirtualProductToCartTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + */ + public function testAddVirtualProductToCart() + { + $sku = 'virtual_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $response = $this->graphQlMutation($query); + + self::assertArrayHasKey('cart', $response['addVirtualProductsToCart']); + self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($sku, $response['addVirtualProductsToCart']['cart']['items'][0]['product']['sku']); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + */ + public function testAddVirtualToNonExistentCart() + { + $sku = 'virtual_product'; + $qty = 1; + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not find a cart with ID \"non_existent_masked_id\"" + ); + + $this->graphQlMutation($query); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + */ + public function testNonExistentProductToCart() + { + $sku = 'virtual_product'; + $qty = 1; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "Could not find a product with SKU \"virtual_product\"" + ); + + $this->graphQlMutation($query); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testAddVirtualProductToCustomerCart() + { + $sku = 'virtual_product'; + $qty = 2; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlMutation($query); + } + + /** + * @param string $maskedQuoteId + * @param string $sku + * @param int $qty + * @return string + */ + private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + { + return <<<QUERY +mutation { + addVirtualProductsToCart( + input: { + cart_id: "{$maskedQuoteId}" + cartItems: [ + { + data: { + qty: $qty + sku: "$sku" + } + } + ] + } + ) { + cart { + items { + qty + product { + sku + } + } + } + } +} +QUERY; + } +} diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product.php b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product.php new file mode 100644 index 0000000000000..e4472464e17ae --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductInterface; +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\Visibility; +use Magento\Framework\Api\DataObjectHelper; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductInterfaceFactory $productFactory */ +$productFactory = $objectManager->get(ProductInterfaceFactory::class); +/** @var DataObjectHelper $dataObjectHelper */ +$dataObjectHelper = Bootstrap::getObjectManager()->get(DataObjectHelper::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +$product = $productFactory->create(); +$productData = [ + ProductInterface::TYPE_ID => Type::TYPE_VIRTUAL, + ProductInterface::ATTRIBUTE_SET_ID => 4, + ProductInterface::SKU => 'virtual_product', + ProductInterface::NAME => 'Virtual Product', + ProductInterface::PRICE => 10, + ProductInterface::VISIBILITY => Visibility::VISIBILITY_BOTH, + ProductInterface::STATUS => Status::STATUS_ENABLED, +]; +$dataObjectHelper->populateWithArray($product, $productData, ProductInterface::class); +/** Out of interface */ +$product + ->setWebsiteIds([1]) + ->setStockData([ + 'qty' => 85.5, + 'is_in_stock' => true, + 'manage_stock' => true, + 'is_qty_decimal' => true + ]); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product_rollback.php b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product_rollback.php new file mode 100644 index 0000000000000..f8d329f574626 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Catalog/_files/virtual_product_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\Registry; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); + +$currentArea = $registry->registry('isSecureArea'); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $productRepository->deleteById('virtual_product'); +} catch (\Magento\Framework\Exception\NoSuchEntityException $e) { + /** + * Tests which are wrapped with MySQL transaction clear all data by transaction rollback. + */ +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', $currentArea); From d598262302bc6852cd05020c5013dd38281bfc03 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Wed, 17 Apr 2019 17:21:10 +0300 Subject: [PATCH 543/603] magento/magento2#19806: Web-Api test fix. --- .../Magento/Downloadable/Api/ProductRepositoryTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php index 4608b255459b6..d0cace993a24a 100644 --- a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php @@ -472,6 +472,10 @@ public function testUpdateDownloadableProductSamplesWithNewFile() 'title' => 'sample2_updated', 'sort_order' => 2, 'sample_type' => 'file', + 'sample_file_content' => [ + 'name' => 'sample2.jpg', + 'file_data' => base64_encode(file_get_contents($this->testImagePath)), + ], ]; $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"] = @@ -606,7 +610,7 @@ protected function deleteProductBySku($productSku) protected function saveProduct($product) { if (isset($product['custom_attributes'])) { - for ($i=0; $i<sizeof($product['custom_attributes']); $i++) { + for ($i = 0, $iMax = count($product['custom_attributes']); $i < $iMax; $i++) { if ($product['custom_attributes'][$i]['attribute_code'] == 'category_ids' && !is_array($product['custom_attributes'][$i]['value']) ) { From 6193247a12b63fd824c8d3f0dfed061fad3175bd Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Wed, 17 Apr 2019 09:27:09 -0500 Subject: [PATCH 544/603] MC-5588: When using MysqlMQ messages are always set to complete even if exception occurs - Fix static tests --- app/code/Magento/MysqlMq/Model/Driver/Queue.php | 2 ++ .../Framework/MessageQueue/_files/valid_queue_input.php | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/MysqlMq/Model/Driver/Queue.php b/app/code/Magento/MysqlMq/Model/Driver/Queue.php index cc9ab2bf30d6c..cbc2e951782f2 100644 --- a/app/code/Magento/MysqlMq/Model/Driver/Queue.php +++ b/app/code/Magento/MysqlMq/Model/Driver/Queue.php @@ -110,11 +110,13 @@ public function subscribe($callback) while (true) { while ($envelope = $this->dequeue()) { try { + // phpcs:ignore Magento2.Functions.DiscouragedFunction call_user_func($callback, $envelope); } catch (\Exception $e) { $this->reject($envelope); } } + // phpcs:ignore Magento2.Functions.DiscouragedFunction sleep($this->interval); } } diff --git a/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php b/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php index e3d9a8a4eb197..46b3ba3414c8a 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php +++ b/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php @@ -23,11 +23,11 @@ "name" => "publisher5.topic", "schema" => [ "schema_type" => "object", - "schema_value" => "Magento\\TestModuleMysqlMq\\Model\\DataObject" + "schema_value" => Magento\TestModuleMysqlMq\Model\DataObject::class ], "response_schema" => [ "schema_type" => "object", - "schema_value" => "Magento\\Customer\\Api\\Data\\CustomerInterface" + "schema_value" => \Magento\Customer\Api\Data\CustomerInterface::class ], "publisher" => "test-publisher-5" ] From ed5dd4d3f47ea7534bb8fe1018b0d6718cb5f99a Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Tue, 16 Apr 2019 23:55:19 -0400 Subject: [PATCH 545/603] Add end to end checkout tests Tests checkout flow for customer and guest. --- .../Quote/Customer/EndToEndCheckoutTest.php | 623 ++++++++++++++++++ 1 file changed, 623 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php new file mode 100644 index 0000000000000..0354356d6927c --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php @@ -0,0 +1,623 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * End to checkout tests for customers and guests + */ +class EndToEndCheckoutTest extends GraphQlAbstract +{ + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php + */ + public function testCheckoutAsCustomer() + { + $email = 'e2e_1@example.com'; + + $this->graphQlMutation($this->buildCreateCustomerMutation($email)); + $authHeader = $this->createAuthHeader($email); + + $cartId = $this->createEmptyCart($authHeader); + $cart = $this->configureQuote($cartId, $authHeader); + + $placeOrderResult = $this->graphQlMutation($this->buildPlaceOrderMutation($cartId), [], '', $authHeader); + $orderId = $placeOrderResult['placeOrder']['order']['order_id']; + $this->assertNotEmpty($orderId); + + $order = $this->getOrderFromHistory($orderId, $authHeader); + $this->assertEquals($cart['prices']['grand_total']['value'], $order['grand_total']); + //TODO: Make additional assertions when order properties are added + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php + */ + public function testCheckoutAsGuest() + { + $email = 'e2e_2@example.com'; + $cartId = $this->createEmptyCart(); + $this->graphQlMutation($this->buildSetGuestEmailOnCartMutation($cartId, $email)); + $this->configureQuote($cartId); + + $placeOrderResult = $this->graphQlMutation($this->buildPlaceOrderMutation($cartId)); + $orderId = $placeOrderResult['placeOrder']['order']['order_id']; + + $this->assertNotEmpty($orderId); + } + + /** + * Configures cart with order placement requirements + * + * @param string $cartId + * @param array $headers + * @return array + */ + private function configureQuote(string $cartId, array $headers = []): array + { + $expectedTotal = 5.99; + $expectedQty = 1; + + $sku = $this->getSku($headers); + $addToCartResult = $this->graphQlMutation($this->buildAddToCartMutation($cartId, $expectedQty, $sku), [], '', $headers); + $cart = $addToCartResult['addSimpleProductsToCart']['cart']; + $this->assertGrandTotal($expectedTotal, $cart); + + $address = $this->setShippingAddress($cartId, $headers); + $shippingMethod = $this->extractFirstAvailableShippingMethod($address); + + $cart = $this->setShippingMethod($cartId, $shippingMethod, $address, $headers); + $expectedTotal += $shippingMethod['amount']; + $this->assertGrandTotal($expectedTotal, $cart); + $this->assertSelectedShippingMethod($shippingMethod, $cart); + + $setBillingAddressResult = $this->graphQlMutation($this->buildSetNewBillingAddressMutation($cartId), [], '', $headers); + $cart = $setBillingAddressResult['setBillingAddressOnCart']['cart']; + $paymentMethod = $this->extractFirstAvailablePaymentMethod($cart); + + $setPaymentResult = $this->graphQlMutation($this->buildSetPaymentMethodMutation($cartId, $paymentMethod), [], '', $headers); + $cart = $setPaymentResult['setPaymentMethodOnCart']['cart']; + $this->assertPaymentMethod($paymentMethod, $cart); + $this->assertGrandTotal($expectedTotal, $cart); + + return $cart; + } + + /** + * Generates customer authentication header for restricted requests + * + * @param string $email + * @return array + */ + private function createAuthHeader(string $email): array + { + $result = $this->graphQlMutation($this->buildLoginMutation($email)); + $token = $result['generateCustomerToken']['token']; + + return ['Authorization' => 'Bearer ' . $token]; + } + + /** + * Creates empty cart for customer or guest + * + * @param array $auth + * @return string + */ + private function createEmptyCart(array $auth = []): string + { + $query = <<<QUERY +mutation { + createEmptyCart +} +QUERY; + + $result = $this->graphQlMutation($query, [], '', $auth); + + return $result['createEmptyCart']; + } + + /** + * Get first SKU returned by catalog search + * + * @param array $auth + * @return string + */ + private function getSku(array $auth): string + { + $result = $this->graphQlQuery($this->buildProductSearchQuery('simple'), [], '', $auth); + $items = $result['products']['items']; + $item = current($items); + + return $item['sku']; + } + + /** + * Set cart shipping address + * + * @param string $cartId + * @param array $auth + * @return array + */ + private function setShippingAddress(string $cartId, array $auth): array + { + $result = $this->graphQlMutation($this->buildSetNewShippingAddressMutation($cartId), [], '', $auth); + $addresses = $result['setShippingAddressesOnCart']['cart']['shipping_addresses']; + + return current($addresses); + } + + /** + * Set cart shipping method + * + * @param string $cartId + * @param array $method + * @param array $address + * @param array $auth + * @return array + */ + private function setShippingMethod(string $cartId, array $method, array $address, array $auth): array + { + $result = $this->graphQlMutation($this->buildSetShippingMethodMutation($cartId, $method, $address), [], '', $auth); + + return $result['setShippingMethodsOnCart']['cart']; + } + + /** + * Get order from history by increment id + * + * @param string $orderId + * @param array $auth + * @return array + */ + private function getOrderFromHistory(string $orderId, array $auth): array + { + $query = <<<QUERY +{ + customerOrders { + items { + increment_id + grand_total + } + } +} +QUERY; + + $result = $this->graphQlQuery($query, [], '', $auth); + $orders = $result['customerOrders']['items']; + + foreach ($orders as $order) { + if ($order['increment_id'] === $orderId) { + return $order; + } + } + + $this->fail(sprintf('No order with increment_id: %s', $orderId)); + } + + /** + * Get first shipping method available from address + * @param array $address + * @return array + */ + private function extractFirstAvailableShippingMethod(array $address): array + { + $methods = $address['available_shipping_methods']; + + return current($methods); + } + + /** + * Get first payment method available from cart + * + * @param array $cart + * @return array + */ + private function extractFirstAvailablePaymentMethod(array $cart): array + { + $methods = $cart['available_payment_methods']; + + return current($methods); + } + + /** + * Assert cart grand total + * + * @param float $expected + * @param array $cart + */ + private function assertGrandTotal(float $expected, array $cart): void + { + $this->assertEquals($expected, $cart['prices']['grand_total']['value']); + } + + /** + * Assert cart payment method + * @param array $method + * @param array $cart + */ + private function assertPaymentMethod(array $method, array $cart): void + { + $this->assertEquals($method['code'], $cart['selected_payment_method']['code']); + } + + /** + * Assert cart shipping method + * + * @param array $expectedMethod + * @param array $cart + */ + private function assertSelectedShippingMethod(array $expectedMethod, array $cart): void + { + $address = current($cart['shipping_addresses']); + $selectedMethod = $address['selected_shipping_method']; + + $this->assertEquals($expectedMethod['carrier_code'], $selectedMethod['carrier_code']); + $this->assertEquals($expectedMethod['method_code'], $selectedMethod['method_code']); + } + + /** + * Build createCustomer mutation + * + * @param string $email + * @return string + */ + private function buildCreateCustomerMutation(string $email): string + { + return <<<QUERY +mutation { + createCustomer( + input: { + firstname: "endto" + lastname: "endtester" + email: "{$email}" + password: "123123Qr" + } + ) { + customer { + id + firstname + lastname + email + } + } +} +QUERY; + } + + /** + * Build generateCustomerToken mutation + * + * @param string $email + * @return string + */ + private function buildLoginMutation(string $email): string + { + return <<<QUERY +mutation { + generateCustomerToken( + email: "{$email}" + password: "123123Qr" + ){ + token + } +} +QUERY; + } + + /** + * Build product search mutation + * + * @param string $term + * @return string + */ + private function buildProductSearchQuery(string $term): string + { + return <<<QUERY +{ + products ( + filter: { + sku: { + like:"{$term}%" + } + } + pageSize: 20 + currentPage: 1 + ) { + items { + sku + } + } +} +QUERY; + } + + /** + * Build addSimpleProductsToCart mutation + * + * @param string $cartId + * @param float $qty + * @param string $sku + * @return string + */ + private function buildAddToCartMutation(string $cartId, float $qty, string $sku): string + { + return <<<QUERY +mutation { + addSimpleProductsToCart( + input: { + cart_id: "{$cartId}" + cartItems: [ + { + data: { + qty: {$qty} + sku: "{$sku}" + } + } + ] + } + ) { + cart { + items { + qty + product { + sku + } + } + prices { + grand_total { + value, + currency + } + } + } + } +} +QUERY; + } + + /** + * Build setShippingAddressesOnCart mutation + * + * @param string $cartId + * @param bool $save + * @return string + */ + private function buildSetNewShippingAddressMutation(string $cartId, bool $save = false): string + { + $save = json_encode($save); + return <<<QUERY +mutation { + setShippingAddressesOnCart( + input: { + cart_id: "$cartId" + shipping_addresses: [ + { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + city: "test city" + region: "TX" + postcode: "887766" + country_code: "US" + telephone: "88776655" + save_in_address_book: {$save} + } + } + ] + } + ) { + cart { + shipping_addresses { + address_id + available_shipping_methods { + carrier_code + method_code + amount + } + } + } + } +} +QUERY; + } + + /** + * Build setShippingMethodsOnCart mutation + * + * @param string $cartId + * @param array $method + * @param array $address + * @return string + */ + private function buildSetShippingMethodMutation(string $cartId, array $method, array $address): string + { + return <<<QUERY +mutation { + setShippingMethodsOnCart(input: { + cart_id: "{$cartId}", + shipping_methods: [ + { + cart_address_id: {$address['address_id']} + carrier_code: "{$method['carrier_code']}" + method_code: "{$method['method_code']}" + } + ] + }) { + cart { + prices { + grand_total { + value, + currency + } + } + shipping_addresses { + selected_shipping_method { + carrier_code + method_code + } + } + } + } +} +QUERY; + + } + + /** + * Build setBillingAddressOnCart mutation + * + * @param string $cartId + * @param bool $save + * @return string + */ + private function buildSetNewBillingAddressMutation(string $cartId, bool $save = false): string + { + $save = json_encode($save); + return <<<QUERY +mutation { + setBillingAddressOnCart( + input: { + cart_id: "{$cartId}" + billing_address: { + address: { + firstname: "test firstname" + lastname: "test lastname" + street: ["test street 1", "test street 2"] + city: "test city" + region: "TX" + postcode: "887766" + country_code: "US" + telephone: "88776655" + save_in_address_book: {$save} + } + } + } + ) { + cart { + available_payment_methods { + code + title + } + billing_address { + firstname + lastname + company + street + city + postcode + telephone + country { + code + label + } + address_type + } + } + } +} +QUERY; + } + + /** + * Build setPaymentMethodOnCart mutation + * + * @param string $cartId + * @param array $payment + * @return string + */ + private function buildSetPaymentMethodMutation(string $cartId, array $payment): string + { + return <<<QUERY +mutation { + setPaymentMethodOnCart( + input: { + cart_id: "{$cartId}" + payment_method: { + code: "{$payment['code']}" + } + } + ) { + cart { + items { + qty + product { + sku + } + } + shipping_addresses { + selected_shipping_method { + carrier_code + method_code + } + } + selected_payment_method { + code + } + prices { + grand_total { + value + currency + } + } + } + } +} +QUERY; + } + + /** + * Build setGuestEmailOnCart mutation + * + * @param string $cartId + * @param string $email + * @return string + */ + private function buildSetGuestEmailOnCartMutation(string $cartId, string $email): string + { + return <<<QUERY +mutation { + setGuestEmailOnCart( + input: { + cart_id: "{$cartId}" + email: "{$email}" + } + ) { + cart { + email + } + } +} +QUERY; + } + + /** + * Build placeOrder mutation + * + * @param string $cartId + * @return string + */ + private function buildPlaceOrderMutation(string $cartId): string + { + return <<<QUERY +mutation { + placeOrder( + input: { + cart_id: "{$cartId}" + } + ) { + order { + order_id + } + } +} +QUERY; + } +} From e046edef2f6749f2f22466c8c36a0c371eee21de Mon Sep 17 00:00:00 2001 From: Vitaliy Honcharenko <vgoncharenko@magento.com> Date: Wed, 17 Apr 2019 09:42:33 -0500 Subject: [PATCH 546/603] MC-15511: Search by default displays incorrect information --- .../Fulltext/Collection/SearchCriteriaResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php b/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php index 255c7885e84b9..32cb85ff750c4 100644 --- a/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php +++ b/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php @@ -79,7 +79,7 @@ public function resolve(): SearchCriteria $this->builder->setPageSize($this->size); $searchCriteria = $this->builder->create(); $searchCriteria->setRequestName($this->searchRequestName); - $searchCriteria->setSortOrders($this->orders); + $searchCriteria->setSortOrders(array_merge(['relevance' => 'DESC'], $this->orders)); $searchCriteria->setCurrentPage($this->currentPage - 1); return $searchCriteria; From e4560fdc298e100f2a9e101797727b42922cce0c Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Wed, 17 Apr 2019 09:55:52 -0500 Subject: [PATCH 547/603] MC-5588: When using MysqlMQ messages are always set to complete even if exception occurs - Fix static tests --- .../Magento/Framework/MessageQueue/_files/valid_queue_input.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php b/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php index 46b3ba3414c8a..ed6e13cfe9fae 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php +++ b/dev/tests/integration/testsuite/Magento/Framework/MessageQueue/_files/valid_queue_input.php @@ -23,7 +23,7 @@ "name" => "publisher5.topic", "schema" => [ "schema_type" => "object", - "schema_value" => Magento\TestModuleMysqlMq\Model\DataObject::class + "schema_value" => \Magento\TestModuleMysqlMq\Model\DataObject::class ], "response_schema" => [ "schema_type" => "object", From 8afaf8097883e4a07a547d5f135f308576a62cff Mon Sep 17 00:00:00 2001 From: Volodymyr Vygovskyi <v.vygovskyi@atwix.com> Date: Wed, 17 Apr 2019 18:40:07 +0300 Subject: [PATCH 548/603] refactoring: changed variable long name --- .../GraphQl/Quote/Customer/AddSimpleProductToCartTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php index 0ff96c03e0990..7b9df8c623c28 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php @@ -54,11 +54,11 @@ public function testAddProductToNonExistentCart() { $sku = 'simple_product'; $qty = 2; - $nonExistentMaskedQuoteId = 'non_existent_masked_id'; - $query = $this->getQuery($nonExistentMaskedQuoteId, $sku, $qty); + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->expectExceptionMessage( - "Could not find a cart with ID \"$nonExistentMaskedQuoteId\"" + "Could not find a cart with ID \"$maskedQuoteId\"" ); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); From b99e9dd262912f35352e4e2e24a7cbb5af725bfa Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 17 Apr 2019 14:57:06 -0500 Subject: [PATCH 549/603] GraphQL-606: [Test coverage] Add virtual product to cart --- .../Customer/AddVirtualProductToCartTest.php | 24 +++++++++++-------- .../Guest/AddVirtualProductToCartTest.php | 5 ++-- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php index f2beef7aa93c8..eaca5332b63bb 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php @@ -28,6 +28,13 @@ class AddVirtualProductToCartTest extends GraphQlAbstract */ private $getMaskedQuoteIdByReservedOrderId; + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php @@ -83,6 +90,7 @@ public function testNonExistentProductToCart() } /** + * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php @@ -102,9 +110,10 @@ public function testAddVirtualProductToGuestCart() } /** + * _security * @magentoApiDataFixture Magento/Customer/_files/three_customers.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php */ public function testAddVirtualProductToAnotherCustomerCart() { @@ -120,15 +129,10 @@ public function testAddVirtualProductToAnotherCustomerCart() $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer2@search.example.com')); } - protected function setUp() - { - $objectManager = Bootstrap::getObjectManager(); - $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); - $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); - } - /** * @param string $maskedQuoteId + * @param string $sku + * @param int $qty * @return string */ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string @@ -140,8 +144,8 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - qty: $qty - sku: "$sku" + qty: {$qty} + sku: "{$sku}" } } ] diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php index 20d7ee031a044..c57c82a37e9a0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php @@ -83,6 +83,7 @@ public function testNonExistentProductToCart() } /** + * _security * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php @@ -117,8 +118,8 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - qty: $qty - sku: "$sku" + qty: {$qty} + sku: "{$sku}" } } ] From 8c34f6c72a92d9018124828b290bff429539e5aa Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 17 Apr 2019 15:08:12 -0500 Subject: [PATCH 550/603] GraphQL-605: [Test coverage] Add simple product to cart --- .../Customer/AddSimpleProductToCartTest.php | 42 ++++++++++--------- .../Guest/AddSimpleProductToCartTest.php | 9 ++-- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php index 7b9df8c623c28..73b3e39721866 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php @@ -28,6 +28,13 @@ class AddSimpleProductToCartTest extends GraphQlAbstract */ private $getMaskedQuoteIdByReservedOrderId; + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php @@ -49,40 +56,39 @@ public function testAddSimpleProductToCart() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ public function testAddProductToNonExistentCart() { $sku = 'simple_product'; $qty = 2; $maskedQuoteId = 'non_existent_masked_id'; - $query = $this->getQuery($maskedQuoteId, $sku, $qty); - - $this->expectExceptionMessage( - "Could not find a cart with ID \"$maskedQuoteId\"" - ); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a product with SKU "simple_product" */ public function testNonExistentProductToCart() { $sku = 'simple_product'; $qty = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); - - $this->expectExceptionMessage( - "Could not find a product with SKU \"simple_product\"" - ); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** + * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php @@ -102,9 +108,10 @@ public function testAddSimpleProductToGuestCart() } /** + * _security * @magentoApiDataFixture Magento/Customer/_files/three_customers.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php */ public function testAddSimpleProductToAnotherCustomerCart() { @@ -120,15 +127,10 @@ public function testAddSimpleProductToAnotherCustomerCart() $this->graphQlMutation($query, [], '', $this->getHeaderMap('customer2@search.example.com')); } - protected function setUp() - { - $objectManager = Bootstrap::getObjectManager(); - $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); - $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); - } - /** * @param string $maskedQuoteId + * @param string $sku + * @param int $qty * @return string */ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string @@ -140,8 +142,8 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - qty: $qty - sku: "$sku" + qty: {$qty} + sku: "{$sku}" } } ] diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php index f4345c9ab4826..9e0693b160851 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php @@ -66,18 +66,17 @@ public function testAddProductToNonExistentCart() /** * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a product with SKU "simple_product" */ public function testNonExistentProductToCart() { $sku = 'simple_product'; $qty = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); - - $this->expectExceptionMessage( - "Could not find a product with SKU \"simple_product\"" - ); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->graphQlMutation($query); } From a241594a44e78f59038127a9b36b30711e16aeb6 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 17 Apr 2019 15:10:47 -0500 Subject: [PATCH 551/603] GraphQL-606: [Test coverage] Add virtual product to cart --- .../Customer/AddVirtualProductToCartTest.php | 18 ++++++++---------- .../Guest/AddVirtualProductToCartTest.php | 18 ++++++++---------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php index eaca5332b63bb..4ec25bb030079 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php @@ -56,36 +56,34 @@ public function testAddVirtualProductToCart() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ public function testAddVirtualToNonExistentCart() { $sku = 'virtual_product'; $qty = 2; $nonExistentMaskedQuoteId = 'non_existent_masked_id'; - $query = $this->getQuery($nonExistentMaskedQuoteId, $sku, $qty); - - $this->expectExceptionMessage( - "Could not find a cart with ID \"$nonExistentMaskedQuoteId\"" - ); + $query = $this->getQuery($nonExistentMaskedQuoteId, $sku, $qty); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a product with SKU "virtual_product" */ public function testNonExistentProductToCart() { $sku = 'virtual_product'; $qty = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); - - $this->expectExceptionMessage( - "Could not find a product with SKU \"virtual_product\"" - ); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php index c57c82a37e9a0..3f2d734635c3e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php @@ -50,35 +50,33 @@ public function testAddVirtualProductToCart() /** * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/virtual_product.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ public function testAddVirtualToNonExistentCart() { $sku = 'virtual_product'; $qty = 1; $maskedQuoteId = 'non_existent_masked_id'; - $query = $this->getQuery($maskedQuoteId, $sku, $qty); - - $this->expectExceptionMessage( - "Could not find a cart with ID \"non_existent_masked_id\"" - ); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->graphQlMutation($query); } /** * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * + * @expectedException \Exception + * @expectedExceptionMessage Could not find a product with SKU "virtual_product" */ public function testNonExistentProductToCart() { $sku = 'virtual_product'; $qty = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); - - $this->expectExceptionMessage( - "Could not find a product with SKU \"virtual_product\"" - ); + $query = $this->getQuery($maskedQuoteId, $sku, $qty); $this->graphQlMutation($query); } From 408e38690ad884049bee9bb8cf73b9ca24aa870a Mon Sep 17 00:00:00 2001 From: Ansari <ziyaurrahman@krishtechnolabs.com> Date: Thu, 18 Apr 2019 10:50:52 +0530 Subject: [PATCH 552/603] disabled comment and qty field when out of stock --- .../Wishlist/view/frontend/templates/item/column/cart.phtml | 4 ++-- .../view/frontend/templates/item/column/comment.phtml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml index c85f41bbf0775..314c40c6ebecd 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml @@ -18,12 +18,12 @@ $allowedQty = $block->getMinMaxQty(); <?php endforeach;?> <div class="box-tocart"> <fieldset class="fieldset"> - <?php if ($item->canHaveQty() && $product->isVisibleInSiteVisibility() && $product->isSaleable()): ?> + <?php if ($item->canHaveQty() && $product->isVisibleInSiteVisibility()): ?> <div class="field qty"> <label class="label" for="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]"><span><?= $block->escapeHtml(__('Qty')) ?></span></label> <div class="control"> <input type="number" data-role="qty" id="qty[<?= /* @noEscape */ $block->escapeHtmlAttr($item->getId()) ?>]" class="input-text qty" data-validate="{'required-number':true,'validate-greater-than-zero':true, 'validate-item-quantity':{'minAllowed':<?= /* @noEscape */ $allowedQty['minAllowed'] ?>,'maxAllowed':<?= /* @noEscape */ $allowedQty['maxAllowed'] ?>}}" - name="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]" value="<?= /* @noEscape */ (int)($block->getAddToCartQty($item) * 1) ?>"> + name="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]" value="<?= /* @noEscape */ (int)($block->getAddToCartQty($item) * 1) ?>" <?= $product->isSaleable() ? '' : 'disabled="disabled"' ?>> </div> </div> <?php endif; ?> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/comment.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/comment.phtml index 17e2404ee23cf..5ab5bc5422e7e 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/comment.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/comment.phtml @@ -17,6 +17,6 @@ $item = $block->getItem(); <span><?= $block->escapeHtml(__('Comment')) ?></span> </label> <div class="control"> - <textarea id="product-item-comment-<?= $block->escapeHtmlAttr($item->getWishlistItemId()) ?>" placeholder="<?= /* @noEscape */ $this->helper('Magento\Wishlist\Helper\Data')->defaultCommentString() ?>" name="description[<?= $block->escapeHtmlAttr($item->getWishlistItemId()) ?>]" title="<?= $block->escapeHtmlAttr(__('Comment')) ?>" class="product-item-comment"><?= ($block->escapeHtml($item->getDescription())) ?></textarea> + <textarea id="product-item-comment-<?= $block->escapeHtmlAttr($item->getWishlistItemId()) ?>" placeholder="<?= /* @noEscape */ $this->helper('Magento\Wishlist\Helper\Data')->defaultCommentString() ?>" name="description[<?= $block->escapeHtmlAttr($item->getWishlistItemId()) ?>]" title="<?= $block->escapeHtmlAttr(__('Comment')) ?>" class="product-item-comment" <?= $item->getProduct()->isSaleable() ? '' : 'disabled="disabled"' ?>><?= ($block->escapeHtml($item->getDescription())) ?></textarea> </div> </div> From be34f65e5001ee3b17fb5a109803b14a50ae8906 Mon Sep 17 00:00:00 2001 From: Ansari <ziyaurrahman@krishtechnolabs.com> Date: Thu, 18 Apr 2019 11:59:52 +0530 Subject: [PATCH 553/603] Resolved git conflict --- .../Wishlist/view/frontend/templates/item/column/cart.phtml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml index 314c40c6ebecd..f296b950f3abb 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml @@ -11,7 +11,9 @@ /** @var \Magento\Wishlist\Model\Item $item */ $item = $block->getItem(); $product = $item->getProduct(); -$allowedQty = $block->getMinMaxQty(); +/** @var \Magento\Wishlist\ViewModel\AllowedQuantity $viewModel */ +$viewModel = $block->getData('allowedQuantityViewModel'); +$allowedQty = $viewModel->setItem($item)->getMinMaxQty(); ?> <?php foreach ($block->getChildNames() as $childName): ?> <?= /* @noEscape */ $block->getLayout()->renderElement($childName, false) ?> @@ -22,7 +24,7 @@ $allowedQty = $block->getMinMaxQty(); <div class="field qty"> <label class="label" for="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]"><span><?= $block->escapeHtml(__('Qty')) ?></span></label> <div class="control"> - <input type="number" data-role="qty" id="qty[<?= /* @noEscape */ $block->escapeHtmlAttr($item->getId()) ?>]" class="input-text qty" data-validate="{'required-number':true,'validate-greater-than-zero':true, 'validate-item-quantity':{'minAllowed':<?= /* @noEscape */ $allowedQty['minAllowed'] ?>,'maxAllowed':<?= /* @noEscape */ $allowedQty['maxAllowed'] ?>}}" + <input type="number" data-role="qty" id="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]" class="input-text qty" data-validate="{'required-number':true,'validate-greater-than-zero':true, 'validate-item-quantity':{'minAllowed':<?= /* @noEscape */ $allowedQty['minAllowed'] ?>,'maxAllowed':<?= /* @noEscape */ $allowedQty['maxAllowed'] ?>}}" name="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]" value="<?= /* @noEscape */ (int)($block->getAddToCartQty($item) * 1) ?>" <?= $product->isSaleable() ? '' : 'disabled="disabled"' ?>> </div> </div> From 92d0f9324b991f2fdd92692ed643f5be60211148 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Thu, 18 Apr 2019 11:16:16 +0300 Subject: [PATCH 554/603] Fix static tests. --- .../Annotation/AnnotationFormatValidator.php | 23 +++++++++++++++---- .../Annotation/MethodArgumentsSniff.php | 13 +++++++---- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php b/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php index b102fa87b76a8..33df6e8ae54f1 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php +++ b/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php @@ -4,6 +4,7 @@ * See COPYING.txt for license details. */ declare(strict_types=1); + namespace Magento\Sniffs\Annotation; use PHP_CodeSniffer\Files\File; @@ -261,14 +262,13 @@ public function validateTagAligningFormat(File $phpcsFile, int $commentStartPtr) $noAlignmentPositions = []; $actualPositions = []; $stackPtr = null; - foreach ($tokens[$commentStartPtr]['comment_tags'] as $position => $tag) { + foreach ($tokens[$commentStartPtr]['comment_tags'] as $tag) { $content = $tokens[$tag]['content']; if (preg_match('/^@/', $content) && ($tokens[$tag]['line'] === $tokens[$tag + 2]['line'])) { $noAlignmentPositions[] = $tokens[$tag + 1]['column'] + 1; $actualPositions[] = $tokens[$tag + 2]['column']; $stackPtr = $stackPtr ?? $tag; } - } if (!$this->allTagsAligned($actualPositions) @@ -281,11 +281,26 @@ public function validateTagAligningFormat(File $phpcsFile, int $commentStartPtr) } } - private function allTagsAligned(array $actualPositions) { + /** + * Check whether all docblock params are aligned. + * + * @param array $actualPositions + * @return bool + */ + private function allTagsAligned(array $actualPositions) + { return count(array_unique($actualPositions)) === 1; } - private function noneTagsAligned(array $actualPositions, array $noAlignmentPositions) { + /** + * Check whether all docblock params are not aligned. + * + * @param array $actualPositions + * @param array $noAlignmentPositions + * @return bool + */ + private function noneTagsAligned(array $actualPositions, array $noAlignmentPositions) + { return $actualPositions === $noAlignmentPositions; } diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php b/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php index 5bd4667c4f4be..50efca9b1ed23 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Annotation/MethodArgumentsSniff.php @@ -124,7 +124,8 @@ private function getMethodArguments(File $phpcsFile, int $openParenthesisPtr, in private function getMethodParameters(array $paramDefinitions): array { $paramName = []; - for ($i = 0; $i < count($paramDefinitions); $i++) { + $paramCount = count($paramDefinitions); + for ($i = 0; $i < $paramCount; $i++) { if (isset($paramDefinitions[$i]['paramName'])) { $paramName[] = $paramDefinitions[$i]['paramName']; } @@ -371,10 +372,11 @@ private function validateDuplicateAnnotationDoesnotExists( $parametersCount = count($paramPointers); if ($argumentsCount <= $parametersCount && $argumentsCount > 0) { $duplicateParameters = []; - for ($i = 0; $i < count($paramDefinitions); $i++) { + $paramCount = count($paramDefinitions); + for ($i = 0; $i < $paramCount; $i++) { if (isset($paramDefinitions[$i]['paramName'])) { $parameterContent = $paramDefinitions[$i]['paramName']; - for ($j = $i + 1; $j < count($paramDefinitions); $j++) { + for ($j = $i + 1; $j < $paramCount; $j++) { if (isset($paramDefinitions[$j]['paramName']) && $parameterContent === $paramDefinitions[$j]['paramName'] ) { @@ -517,7 +519,7 @@ private function validateMethodParameterAnnotations( $paramPointers ); $tokens = $phpcsFile->getTokens(); - for ($ptr = 0; $ptr < count($methodArguments); $ptr++) { + for ($ptr = 0; $ptr < $argumentCount; $ptr++) { if (isset($paramPointers[$ptr])) { $this->validateArgumentNameInParameterAnnotationExists( $stackPtr, @@ -614,7 +616,8 @@ private function validateFormattingConsistency( $argumentPositions = []; $commentPositions = []; $tokens = $phpcsFile->getTokens(); - for ($ptr = 0; $ptr < count($methodArguments); $ptr++) { + $argumentCount = count($methodArguments); + for ($ptr = 0; $ptr < $argumentCount; $ptr++) { if (isset($paramPointers[$ptr])) { $paramContent = $tokens[$paramPointers[$ptr] + 2]['content']; $paramDefinition = $paramDefinitions[$ptr]; From c2e7399d4082cdc1ab1e5b11195f7486b32cefc8 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Thu, 18 Apr 2019 12:04:54 +0300 Subject: [PATCH 555/603] Fix static tests. --- .../Catalog/Api/Data/CategoryInterface.php | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Api/Data/CategoryInterface.php b/app/code/Magento/Catalog/Api/Data/CategoryInterface.php index c1ca89f51ea58..1940a0ac80c0b 100644 --- a/app/code/Magento/Catalog/Api/Data/CategoryInterface.php +++ b/app/code/Magento/Catalog/Api/Data/CategoryInterface.php @@ -1,7 +1,5 @@ <?php /** - * Category data interface - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -9,6 +7,8 @@ namespace Magento\Catalog\Api\Data; /** + * Category data interface. + * * @api * @since 100.0.2 */ @@ -46,11 +46,15 @@ interface CategoryInterface extends \Magento\Framework\Api\CustomAttributesDataI /**#@-*/ /** + * Retrieve category id. + * * @return int|null */ public function getId(); /** + * Set category id. + * * @param int $id * @return $this */ @@ -132,60 +136,82 @@ public function getLevel(); public function setLevel($level); /** + * Retrieve children ids comma separated. + * * @return string|null */ public function getChildren(); /** + * Retrieve category creation date and time. + * * @return string|null */ public function getCreatedAt(); /** + * Set category creation date and time. + * * @param string $createdAt * @return $this */ public function setCreatedAt($createdAt); /** + * Retrieve category last update date and time. + * * @return string|null */ public function getUpdatedAt(); /** + * Set category last update date and time. + * * @param string $updatedAt * @return $this */ public function setUpdatedAt($updatedAt); /** + * Retrieve category full path. + * * @return string|null */ public function getPath(); /** + * Set category full path. + * * @param string $path * @return $this */ public function setPath($path); /** + * Retrieve available sort by for category. + * * @return string[]|null */ public function getAvailableSortBy(); /** + * Set available sort by for category. + * * @param string[]|string $availableSortBy * @return $this */ public function setAvailableSortBy($availableSortBy); /** + * Get category is included in menu. + * * @return bool|null */ public function getIncludeInMenu(); /** + * Set category is included in menu. + * * @param bool $includeInMenu * @return $this */ From 0ade930796f0857030823dcce9c2bcb4a1a483bd Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 18 Apr 2019 13:22:46 +0300 Subject: [PATCH 556/603] magento/magento2#21711: Static test fix. --- .../Downloadable/Observer/UpdateLinkPurchasedObserver.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php b/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php index 067c91981cd89..db391ccda6866 100644 --- a/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php +++ b/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php @@ -10,7 +10,6 @@ use Magento\Framework\Event\ObserverInterface; /** - * Class UpdateLinkPurchasedObserver * Assign Downloadable links to customer created after issuing guest order. */ class UpdateLinkPurchasedObserver implements ObserverInterface @@ -47,9 +46,10 @@ public function __construct( } /** - * re-save order data after order update + * Re-save order data after order update. + * * @param \Magento\Framework\Event\Observer $observer - * @return $this|void + * @return $this */ public function execute(\Magento\Framework\Event\Observer $observer) { From 432334e33cf028edd74aaf04e4c31468c4808d80 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 18 Apr 2019 14:22:27 +0300 Subject: [PATCH 557/603] magento/magento2#22339: Static test fix. --- .../Magento/Framework/Setup/Patch/DependentPatchInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php b/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php index 21fafd273f9ed..7573441fa9466 100644 --- a/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php +++ b/lib/internal/Magento/Framework/Setup/Patch/DependentPatchInterface.php @@ -20,7 +20,7 @@ interface DependentPatchInterface /** * Get array of patches that have to be executed prior to this. * - * example of implementation: + * Example of implementation: * * [ * \Vendor_Name\Module_Name\Setup\Patch\Patch1::class, From fd92027ac2c34c47ff1f09dafbd1c01b549adc47 Mon Sep 17 00:00:00 2001 From: hiren pandya <hiren.pandya@krishtechnolabs.com> Date: Thu, 18 Apr 2019 17:28:53 +0530 Subject: [PATCH 558/603] Resolve issue of Backup tool not correctly detecting .maintenance.flag --- app/code/Magento/Backup/Controller/Adminhtml/Index/Create.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Backup/Controller/Adminhtml/Index/Create.php b/app/code/Magento/Backup/Controller/Adminhtml/Index/Create.php index 53f45aff50cbc..715df71501f7e 100644 --- a/app/code/Magento/Backup/Controller/Adminhtml/Index/Create.php +++ b/app/code/Magento/Backup/Controller/Adminhtml/Index/Create.php @@ -55,7 +55,9 @@ public function execute() $this->_coreRegistry->register('backup_manager', $backupManager); if ($this->getRequest()->getParam('maintenance_mode')) { - if (!$this->maintenanceMode->set(true)) { + $this->maintenanceMode->set(true); + + if (!$this->maintenanceMode->isOn()) { $response->setError( __( 'You need more permissions to activate maintenance mode right now.' From e949e85159dd00640106be24ff72b79441cba121 Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Wed, 17 Apr 2019 09:36:28 +0300 Subject: [PATCH 559/603] Don't skip row on import if image not available. --- .../Model/Import/Product.php | 8 +++- .../Model/Import/ProductTest.php | 39 +++++++++++++++++++ ...ucts_to_import_with_non_existing_image.csv | 2 + 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_non_existing_image.csv diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index 404c31296e4dd..c6ce3e24ce02f 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -1798,7 +1798,13 @@ protected function _saveProducts() $uploadedImages[$columnImage] = $uploadedFile; } else { unset($rowData[$column]); - $this->skipRow($rowNum, ValidatorInterface::ERROR_MEDIA_URL_NOT_ACCESSIBLE); + $this->addRowError( + ValidatorInterface::ERROR_MEDIA_URL_NOT_ACCESSIBLE, + $rowNum, + null, + null, + ProcessingError::ERROR_LEVEL_NOT_CRITICAL + ); } } else { $uploadedFile = $uploadedImages[$columnImage]; 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 c4c6d3ba2d1d2..dd2237d6080ca 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -1590,6 +1590,45 @@ public function testAddUpdateProductWithInvalidUrlKeys() : void } } + /** + * Make sure the non existing image in the csv file won't erase the qty key of the existing products. + * + * @magentoDataFixture Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_non_existing_image.csv + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ + public function testImportWithNonExistingImage() + { + $products = [ + 'simple_new' => 100, + ]; + $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_non_existing_image.csv', + 'directory' => $directory + ] + ); + + $errors = $this->_model->setParameters( + ['behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, 'entity' => 'catalog_product'] + ) + ->setSource($source) + ->validateData(); + + $this->assertTrue($errors->getErrorsCount() == 0); + $this->_model->importData(); + + $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + foreach ($products as $productSku => $productQty) { + $product = $productRepository->get($productSku); + $stockItem = $product->getExtensionAttributes()->getStockItem(); + $this->assertEquals($productQty, $stockItem->getQty()); + } + } + /** * @magentoDataFixture Magento/Catalog/_files/product_simple_with_url_key.php * @magentoDbIsolation disabled 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 new file mode 100644 index 0000000000000..8122433a8c9e1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_non_existing_image.csv @@ -0,0 +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",,,,,,,, From 3f5d1ff2834ae69e1ced5b8abf2d51c543111422 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Thu, 18 Apr 2019 16:18:31 +0300 Subject: [PATCH 560/603] MC-5266: Create not anchor subcategory specifying all fields --- .../Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml index ea6808ee2a7f5..663439fd62a1d 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml @@ -17,7 +17,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForm" /> </variation> <variation name="CreateCategoryEntityTestVariation2_RootCategory_AllFields"> - <data name="issue" xsi:type="string">MAGETWO-60635: [CE][Categories] Design update dates are incorrect after save</data> <data name="description" xsi:type="string">Create root category with all fields</data> <data name="addCategory" xsi:type="string">addRootCategory</data> <data name="category/data/is_active" xsi:type="string">Yes</data> @@ -58,7 +57,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryPage" /> </variation> <variation name="CreateCategoryEntityTestVariation4_Subcategory_AllFields"> - <data name="issue" xsi:type="string">MAGETWO-60635: [CE][Categories] Design update dates are incorrect after save</data> <data name="description" xsi:type="string">Create not anchor subcategory specifying all fields</data> <data name="addCategory" xsi:type="string">addSubcategory</data> <data name="category/data/parent_id/dataset" xsi:type="string">default_category</data> From 149294b87a63ef89da774862d5ebcacee47975ff Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 18 Apr 2019 16:50:30 +0300 Subject: [PATCH 561/603] magento/magento2#21816: Static test fix. --- .../Magento/Framework/Data/Form/Element/Textarea.php | 10 +++++----- .../Data/Test/Unit/Form/Element/TextareaTest.php | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php b/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php index 47c89e0615df3..1970ebeb9544e 100644 --- a/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php @@ -4,15 +4,15 @@ * See COPYING.txt for license details. */ -/** - * Form textarea element - * - * @author Magento Core Team <core@magentocommerce.com> - */ namespace Magento\Framework\Data\Form\Element; use Magento\Framework\Escaper; +/** + * Form textarea element. + * + * @author Magento Core Team <core@magentocommerce.com> + */ class Textarea extends AbstractElement { /** diff --git a/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/TextareaTest.php b/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/TextareaTest.php index 4653aa2a50769..eec85ca35775d 100644 --- a/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/TextareaTest.php +++ b/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/TextareaTest.php @@ -4,11 +4,11 @@ * See COPYING.txt for license details. */ -/** - * Tests for \Magento\Framework\Data\Form\Element\Textarea - */ namespace Magento\Framework\Data\Test\Unit\Form\Element; +/** + * Tests for \Magento\Framework\Data\Form\Element\Textarea class. + */ class TextareaTest extends \PHPUnit\Framework\TestCase { /** From 6374f9ddd3c51aa1e4cc96b5e2339c236028c665 Mon Sep 17 00:00:00 2001 From: hiren pandya <hiren.pandya@krishtechnolabs.com> Date: Thu, 18 Apr 2019 19:57:29 +0530 Subject: [PATCH 562/603] Resolve Rollback issue --- .../Magento/Backup/Controller/Adminhtml/Index/Rollback.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php b/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php index 0451f6ed09bd1..51fa0ef8f65ad 100644 --- a/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php +++ b/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php @@ -82,7 +82,9 @@ public function execute() } if ($this->getRequest()->getParam('maintenance_mode')) { - if (!$this->maintenanceMode->set(true)) { + $this->maintenanceMode->set(true); + + if (!$this->maintenanceMode->isOn()) { $response->setError( __( 'You need more permissions to activate maintenance mode right now.' From b5683e86bf6ca0554ca63e3fe9b93ab73558370f Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Thu, 18 Apr 2019 10:21:48 -0500 Subject: [PATCH 563/603] Fix for issue #21299. Change HEAD action mapping to GET action interface and add HEAD request handling --- .../Framework/App/Test/Unit/HttpTest.php | 10 +++---- .../Test/Unit/Transfer/Adapter/HttpTest.php | 4 +-- .../Framework/File/Transfer/Adapter/Http.php | 27 +++++++++++-------- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php index 23e58bd3df1e8..dbb315e88a526 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/HttpTest.php @@ -181,13 +181,9 @@ public function testLaunchException() $this->setUpLaunch(); $this->frontControllerMock->expects($this->once()) ->method('dispatch') - ->with($this->requestMock)->will( - $this->returnCallback( - function () { - // phpcs:ignore Magento2.Exceptions.DirectThrow - throw new \Exception('Message'); - } - ) + ->with($this->requestMock) + ->willThrowException( + new \Exception('Message') ); $this->http->launch(); } diff --git a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php index 8147ed4eb0005..023c4cc4ddba6 100644 --- a/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php +++ b/lib/internal/Magento/Framework/File/Test/Unit/Transfer/Adapter/HttpTest.php @@ -73,10 +73,10 @@ public function testSend(): void $this->mime->expects($this->once()) ->method('getMimeType') ->with($file) - ->will($this->returnValue($contentType)); + ->willReturn($contentType); $this->request->expects($this->once()) ->method('isHead') - ->will($this->returnValue(false)); + ->willReturn(false); $this->expectOutputString(file_get_contents($file)); $this->object->send($file); diff --git a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php index 8c09fbdc45124..c57952e7027d5 100644 --- a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php +++ b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php @@ -6,40 +6,45 @@ namespace Magento\Framework\File\Transfer\Adapter; +use Magento\Framework\HTTP\PhpEnvironment\Response; +use Magento\Framework\File\Mime; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\App\ObjectManager; + /** * File adapter to send the file to the client. */ class Http { /** - * @var \Magento\Framework\HTTP\PhpEnvironment\Response + * @var Response */ private $response; /** - * @var \Magento\Framework\File\Mime + * @var Mime */ private $mime; /** - * @var \Magento\Framework\App\Request\Http + * @var HttpRequest */ private $request; /** - * @param \Magento\Framework\HTTP\PhpEnvironment\Response $response - * @param \Magento\Framework\File\Mime $mime - * @param \Magento\Framework\App\Request\Http|null $request + * @param Response $response + * @param Mime $mime + * @param HttpRequest|null $request */ public function __construct( - \Magento\Framework\HTTP\PhpEnvironment\Response $response, - \Magento\Framework\File\Mime $mime, - \Magento\Framework\App\Request\Http $request = null + Response $response, + Mime $mime, + HttpRequest $request = null ) { $this->response = $response; $this->mime = $mime; - $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); - $this->request = $request ?: $objectManager->get(\Magento\Framework\App\Request\Http::class); + $objectManager = ObjectManager::getInstance(); + $this->request = $request ?: $objectManager->get(HttpRequest::class); } /** From 740e4bd80021fbfc8a781c3137c4b9c5cc0b176c Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Thu, 18 Apr 2019 10:42:25 -0500 Subject: [PATCH 564/603] Fix for issue #21299. Change HEAD action mapping to GET action interface and add HEAD request handling --- lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php index c57952e7027d5..cd42c8d04b477 100644 --- a/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php +++ b/lib/internal/Magento/Framework/File/Transfer/Adapter/Http.php @@ -10,6 +10,7 @@ use Magento\Framework\File\Mime; use Magento\Framework\App\Request\Http as HttpRequest; use Magento\Framework\App\ObjectManager; +use Zend\Http\Headers; /** * File adapter to send the file to the client. @@ -114,7 +115,7 @@ private function getFilePath($options): string private function prepareResponse($options, string $filepath): void { $mimeType = $this->mime->getMimeType($filepath); - if (is_array($options) && isset($options['headers']) && $options['headers'] instanceof \Zend\Http\Headers) { + if (is_array($options) && isset($options['headers']) && $options['headers'] instanceof Headers) { $this->response->setHeaders($options['headers']); } $this->response->setHeader('Content-length', filesize($filepath)); From b14d3246315fb4454b1aaf1c7c1e4e33056fc47d Mon Sep 17 00:00:00 2001 From: Iryna Lagno <ilagno@adobe.com> Date: Thu, 18 Apr 2019 11:24:06 -0500 Subject: [PATCH 565/603] MAGETWO-99210: Magento\Install\Test\TestCase\InstallTest is failing on php 7.1 -revert MQE-1352: bug fix in dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php --- .../lib/Magento/Mtf/Util/Command/Cli.php | 41 +++-------- .../Mtf/Util/Command/File/Export/Reader.php | 38 +++------- .../Command/File/Export/ReaderInterface.php | 2 +- .../lib/Magento/Mtf/Util/Command/File/Log.php | 38 +++------- .../Mtf/Util/Command/GeneratedCode.php | 39 ++--------- .../lib/Magento/Mtf/Util/Command/Locales.php | 42 +++-------- .../Magento/Mtf/Util/Command/PathChecker.php | 43 +++--------- .../lib/Magento/Mtf/Util/Command/Website.php | 40 ++++------- .../CurlTransport/BackendDecorator.php | 69 +++++-------------- .../CurlTransport/WebapiDecorator.php | 32 +-------- .../TestCase/ExportAdvancedPricingTest.php | 7 +- .../TestCase/ExportCustomerAddressesTest.php | 3 +- dev/tests/functional/utils/authenticate.php | 29 -------- dev/tests/functional/utils/command.php | 31 +++++---- .../utils/deleteMagentoGeneratedCode.php | 12 +--- dev/tests/functional/utils/export.php | 46 +++++++------ dev/tests/functional/utils/locales.php | 31 ++++----- dev/tests/functional/utils/log.php | 29 ++++---- dev/tests/functional/utils/pathChecker.php | 24 +++---- dev/tests/functional/utils/website.php | 47 ++++++------- 20 files changed, 200 insertions(+), 443 deletions(-) delete mode 100644 dev/tests/functional/utils/authenticate.php diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php index f0abd280f3ebc..8fa22122cce89 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php @@ -8,7 +8,6 @@ use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; -use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * Perform bin/magento commands from command line for functional tests executions. @@ -18,7 +17,7 @@ class Cli /** * Url to command.php. */ - const URL = '/dev/tests/functional/utils/command.php'; + const URL = 'dev/tests/functional/utils/command.php'; /** * Curl transport protocol. @@ -27,21 +26,12 @@ class Cli */ private $transport; - /** - * Webapi handler. - * - * @var WebapiDecorator - */ - private $webapiHandler; - /** * @param CurlTransport $transport - * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) + public function __construct(CurlTransport $transport) { $this->transport = $transport; - $this->webapiHandler = $webapiHandler; } /** @@ -53,31 +43,22 @@ public function __construct(CurlTransport $transport, WebapiDecorator $webapiHan */ public function execute($command, $options = []) { - $this->transport->write( - rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, - $this->prepareParamArray($command, $options), - CurlInterface::POST, - [] - ); - $this->transport->read(); - $this->transport->close(); + $curl = $this->transport; + $curl->write($this->prepareUrl($command, $options), [], CurlInterface::GET); + $curl->read(); + $curl->close(); } /** - * Prepare parameter array. + * Prepare url. * * @param string $command * @param array $options [optional] - * @return array + * @return string */ - private function prepareParamArray($command, $options = []) + private function prepareUrl($command, $options = []) { - if (!empty($options)) { - $command .= ' ' . implode(' ', $options); - } - return [ - 'token' => urlencode($this->webapiHandler->getWebapiToken()), - 'command' => urlencode($command) - ]; + $command .= ' ' . implode(' ', $options); + return $_ENV['app_frontend_url'] . self::URL . '?command=' . urlencode($command); } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php index 69df78a5cad64..79dd435ada7e6 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php @@ -3,12 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Mtf\Util\Command\File\Export; use Magento\Mtf\ObjectManagerInterface; use Magento\Mtf\Util\Protocol\CurlTransport; use Magento\Mtf\Util\Protocol\CurlInterface; -use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * File reader for Magento export files. @@ -36,29 +36,16 @@ class Reader implements ReaderInterface */ private $transport; - /** - * Webapi handler. - * - * @var WebapiDecorator - */ - private $webapiHandler; - /** * @param ObjectManagerInterface $objectManager * @param CurlTransport $transport - * @param WebapiDecorator $webapiHandler * @param string $template */ - public function __construct( - ObjectManagerInterface $objectManager, - CurlTransport $transport, - WebapiDecorator $webapiHandler, - $template - ) { + public function __construct(ObjectManagerInterface $objectManager, CurlTransport $transport, $template) + { $this->objectManager = $objectManager; $this->template = $template; $this->transport = $transport; - $this->webapiHandler = $webapiHandler; } /** @@ -83,27 +70,20 @@ public function getData() */ private function getFiles() { - $this->transport->write( - rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, - $this->prepareParamArray(), - CurlInterface::POST, - [] - ); + $this->transport->write($this->prepareUrl(), [], CurlInterface::GET); $serializedFiles = $this->transport->read(); $this->transport->close(); + // phpcs:ignore Magento2.Security.InsecureFunction return unserialize($serializedFiles); } /** - * Prepare parameter array. + * Prepare url. * - * @return array + * @return string */ - private function prepareParamArray() + private function prepareUrl() { - return [ - 'token' => urlencode($this->webapiHandler->getWebapiToken()), - 'template' => urlencode($this->template) - ]; + return $_ENV['app_frontend_url'] . self::URL . '?template=' . urlencode($this->template); } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php index 3666e8643efa3..93f7cf1ce9764 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php @@ -14,7 +14,7 @@ interface ReaderInterface /** * Url to export.php. */ - const URL = '/dev/tests/functional/utils/export.php'; + const URL = 'dev/tests/functional/utils/export.php'; /** * Exporting files as Data object from Magento. diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Log.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Log.php index 820a5b0a82228..f4e55682857a2 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Log.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Log.php @@ -7,7 +7,6 @@ namespace Magento\Mtf\Util\Command\File; use Magento\Mtf\Util\Protocol\CurlTransport; -use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * Get content of log file in var/log folder. @@ -17,7 +16,7 @@ class Log /** * Url to log.php. */ - const URL = '/dev/tests/functional/utils/log.php'; + const URL = 'dev/tests/functional/utils/log.php'; /** * Curl transport protocol. @@ -26,21 +25,12 @@ class Log */ private $transport; - /** - * Webapi handler. - * - * @var WebapiDecorator - */ - private $webapiHandler; - /** * @param CurlTransport $transport - * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) + public function __construct(CurlTransport $transport) { $this->transport = $transport; - $this->webapiHandler = $webapiHandler; } /** @@ -51,28 +41,22 @@ public function __construct(CurlTransport $transport, WebapiDecorator $webapiHan */ public function getFileContent($name) { - $this->transport->write( - rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, - $this->prepareParamArray($name), - CurlInterface::POST, - [] - ); - $data = $this->transport->read(); - $this->transport->close(); + $curl = $this->transport; + $curl->write($this->prepareUrl($name), [], CurlTransport::GET); + $data = $curl->read(); + $curl->close(); + // phpcs:ignore Magento2.Security.InsecureFunction return unserialize($data); } /** - * Prepare parameter array. + * Prepare url. * * @param string $name - * @return array + * @return string */ - private function prepareParamArray($name) + private function prepareUrl($name) { - return [ - 'token' => urlencode($this->webapiHandler->getWebapiToken()), - 'name' => urlencode($name) - ]; + return $_ENV['app_frontend_url'] . self::URL . '?name=' . urlencode($name); } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/GeneratedCode.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/GeneratedCode.php index a9fefa25ffa24..dde3409ed1562 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/GeneratedCode.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/GeneratedCode.php @@ -7,7 +7,6 @@ use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; -use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * GeneratedCode removes generated code of Magento (like generated/code and generated/metadata). @@ -17,7 +16,7 @@ class GeneratedCode /** * Url to deleteMagentoGeneratedCode.php. */ - const URL = '/dev/tests/functional/utils/deleteMagentoGeneratedCode.php'; + const URL = 'dev/tests/functional/utils/deleteMagentoGeneratedCode.php'; /** * Curl transport protocol. @@ -26,21 +25,12 @@ class GeneratedCode */ private $transport; - /** - * Webapi handler. - * - * @var WebapiDecorator - */ - private $webapiHandler; - /** * @param CurlTransport $transport - * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) + public function __construct(CurlTransport $transport) { $this->transport = $transport; - $this->webapiHandler = $webapiHandler; } /** @@ -50,25 +40,10 @@ public function __construct(CurlTransport $transport, WebapiDecorator $webapiHan */ public function delete() { - $this->transport->write( - rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, - $this->prepareParamArray(), - CurlInterface::POST, - [] - ); - $this->transport->read(); - $this->transport->close(); - } - - /** - * Prepare parameter array. - * - * @return array - */ - private function prepareParamArray() - { - return [ - 'token' => urlencode($this->webapiHandler->getWebapiToken()) - ]; + $url = $_ENV['app_frontend_url'] . self::URL; + $curl = $this->transport; + $curl->write($url, [], CurlInterface::GET); + $curl->read(); + $curl->close(); } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Locales.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Locales.php index a55d803f43087..f669d91f2f2e5 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Locales.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Locales.php @@ -7,7 +7,6 @@ use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; -use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * Returns array of locales depends on fetching type. @@ -27,7 +26,7 @@ class Locales /** * Url to locales.php. */ - const URL = '/dev/tests/functional/utils/locales.php'; + const URL = 'dev/tests/functional/utils/locales.php'; /** * Curl transport protocol. @@ -36,21 +35,12 @@ class Locales */ private $transport; - /** - * Webapi handler. - * - * @var WebapiDecorator - */ - private $webapiHandler; - /** * @param CurlTransport $transport Curl transport protocol - * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) + public function __construct(CurlTransport $transport) { $this->transport = $transport; - $this->webapiHandler = $webapiHandler; } /** @@ -61,28 +51,12 @@ public function __construct(CurlTransport $transport, WebapiDecorator $webapiHan */ public function getList($type = self::TYPE_ALL) { - $this->transport->write( - rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, - $this->prepareParamArray($type), - CurlInterface::POST, - [] - ); - $result = $this->transport->read(); - $this->transport->close(); - return explode('|', $result); - } + $url = $_ENV['app_frontend_url'] . self::URL . '?type=' . $type; + $curl = $this->transport; + $curl->write($url, [], CurlInterface::GET); + $result = $curl->read(); + $curl->close(); - /** - * Prepare parameter array. - * - * @param string $type - * @return array - */ - private function prepareParamArray($type) - { - return [ - 'token' => urlencode($this->webapiHandler->getWebapiToken()), - 'type' => urlencode($type) - ]; + return explode('|', $result); } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/PathChecker.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/PathChecker.php index 4b12f6eec87aa..fd1f746a6f09c 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/PathChecker.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/PathChecker.php @@ -7,7 +7,6 @@ use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; -use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * PathChecker checks that path to file or directory exists. @@ -17,7 +16,7 @@ class PathChecker /** * Url to checkPath.php. */ - const URL = '/dev/tests/functional/utils/pathChecker.php'; + const URL = 'dev/tests/functional/utils/pathChecker.php'; /** * Curl transport protocol. @@ -27,21 +26,11 @@ class PathChecker private $transport; /** - * Webapi handler. - * - * @var WebapiDecorator - */ - private $webapiHandler; - - /** - * @constructor * @param CurlTransport $transport - * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) + public function __construct(CurlTransport $transport) { $this->transport = $transport; - $this->webapiHandler = $webapiHandler; } /** @@ -52,28 +41,12 @@ public function __construct(CurlTransport $transport, WebapiDecorator $webapiHan */ public function pathExists($path) { - $this->transport->write( - rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, - $this->prepareParamArray($path), - CurlInterface::POST, - [] - ); - $result = $this->transport->read(); - $this->transport->close(); - return strpos($result, 'path exists: true') !== false; - } + $url = $_ENV['app_frontend_url'] . self::URL . '?path=' . urlencode($path); + $curl = $this->transport; + $curl->write($url, [], CurlInterface::GET); + $result = $curl->read(); + $curl->close(); - /** - * Prepare parameter array. - * - * @param string $path - * @return array - */ - private function prepareParamArray($path) - { - return [ - 'token' => urlencode($this->webapiHandler->getWebapiToken()), - 'path' => urlencode($path) - ]; + return strpos($result, 'path exists: true') !== false; } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php index fec20bb2a8715..7d73634c0360d 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php @@ -3,11 +3,11 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Mtf\Util\Command; use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; -use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * Perform Website folder creation for functional tests executions. @@ -17,7 +17,7 @@ class Website /** * Url to website.php. */ - const URL = '/dev/tests/functional/utils/website.php'; + const URL = 'dev/tests/functional/utils/website.php'; /** * Curl transport protocol. @@ -26,22 +26,13 @@ class Website */ private $transport; - /** - * Webapi handler. - * - * @var WebapiDecorator - */ - private $webapiHandler; - /** * @constructor * @param CurlTransport $transport - * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) + public function __construct(CurlTransport $transport) { $this->transport = $transport; - $this->webapiHandler = $webapiHandler; } /** @@ -52,28 +43,21 @@ public function __construct(CurlTransport $transport, WebapiDecorator $webapiHan */ public function create($websiteCode) { - $this->transport->addOption(CURLOPT_HEADER, 1); - $this->transport->write( - rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, - $this->prepareParamArray($websiteCode), - CurlInterface::POST, - [] - ); - $this->transport->read(); - $this->transport->close(); + $curl = $this->transport; + $curl->addOption(CURLOPT_HEADER, 1); + $curl->write($this->prepareUrl($websiteCode), [], CurlInterface::GET); + $curl->read(); + $curl->close(); } /** - * Prepare parameter array. + * Prepare url. * * @param string $websiteCode - * @return array + * @return string */ - private function prepareParamArray($websiteCode) + private function prepareUrl($websiteCode) { - return [ - 'token' => urlencode($this->webapiHandler->getWebapiToken()), - 'website_code' => urlencode($websiteCode) - ]; + return $_ENV['app_frontend_url'] . self::URL . '?website_code=' . urlencode($websiteCode); } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php index d7026e9b8efb3..b1c552370835c 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php @@ -63,56 +63,24 @@ public function __construct(CurlTransport $transport, DataInterface $configurati */ protected function authorize() { - // There are situations where magento application backend url could be slightly different from the environment - // variable we know. It could be intentionally (e.g. InstallTest) or unintentionally. We would still want tests - // to run in this case. - // When the original app_backend_url does not work, we will try 4 variants of the it. i.e. with and without - // url rewrite, http and https. - $urls = []; - $originalUrl = rtrim($_ENV['app_backend_url'], '/') . '/'; - $urls[] = $originalUrl; - // It could be the case that the page needs a refresh, so we will try the original one twice. - $urls[] = $originalUrl; - if (strpos($originalUrl, '/index.php') !== false) { - $url2 = str_replace('/index.php', '', $originalUrl); - } else { - $url2 = $originalUrl . 'index.php/'; - } - $urls[] = $url2; - if (strpos($originalUrl, 'https') !== false) { - $urls[] = str_replace('https', 'http', $originalUrl); - } else { - $urls[] = str_replace('http', 'https', $url2); - } - - $isAuthorized = false; - foreach ($urls as $url) { - try { - // Perform GET to backend url so form_key is set - $this->transport->write($url, [], CurlInterface::GET); - $this->read(); - - $authUrl = $url . $this->configuration->get('application/0/backendLoginUrl/0/value'); - $data = [ - 'login[username]' => $this->configuration->get('application/0/backendLogin/0/value'), - 'login[password]' => $this->configuration->get('application/0/backendPassword/0/value'), - 'form_key' => $this->formKey, - ]; - - $this->transport->write($authUrl, $data, CurlInterface::POST); - $response = $this->read(); - if (strpos($response, 'login-form') !== false) { - continue; - } - $isAuthorized = true; - $_ENV['app_backend_url'] = $url; - break; - } catch (\Exception $e) { - continue; - } - } - if ($isAuthorized == false) { - throw new \Exception('Admin user cannot be logged in by curl handler!'); + // Perform GET to backend url so form_key is set + $url = $_ENV['app_backend_url']; + $this->transport->write($url, [], CurlInterface::GET); + $this->read(); + + $url = $_ENV['app_backend_url'] . $this->configuration->get('application/0/backendLoginUrl/0/value'); + $data = [ + 'login[username]' => $this->configuration->get('application/0/backendLogin/0/value'), + 'login[password]' => $this->configuration->get('application/0/backendPassword/0/value'), + 'form_key' => $this->formKey, + ]; + $this->transport->write($url, $data, CurlInterface::POST); + $response = $this->read(); + if (strpos($response, 'login-form') !== false) { + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \Exception( + 'Admin user cannot be logged in by curl handler!' + ); } } @@ -144,6 +112,7 @@ public function write($url, $params = [], $method = CurlInterface::POST, $header if ($this->formKey) { $params['form_key'] = $this->formKey; } else { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception(sprintf('Form key is absent! Url: "%s" Response: "%s"', $url, $this->response)); } $this->transport->write($url, http_build_query($params), $method, $headers); diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/WebapiDecorator.php b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/WebapiDecorator.php index df5ab45a3f96d..3aa756904ab00 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/WebapiDecorator.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/WebapiDecorator.php @@ -70,13 +70,6 @@ class WebapiDecorator implements CurlInterface */ protected $response; - /** - * Webapi token. - * - * @var string - */ - protected $webapiToken; - /** * @construct * @param ObjectManager $objectManager @@ -117,9 +110,6 @@ protected function init() $integration->persist(); $this->setConfiguration($integration); - $this->webapiToken = $integration->getToken(); - } else { - $this->webapiToken = $integrationToken; } } @@ -171,13 +161,7 @@ protected function setConfiguration(Integration $integration) */ protected function isValidIntegration() { - $url = rtrim($_ENV['app_frontend_url'], '/'); - if (strpos($url, 'index.php') === false) { - $url .= '/index.php/rest/V1/modules'; - } else { - $url .= '/rest/V1/modules'; - } - $this->write($url, [], CurlInterface::GET); + $this->write($_ENV['app_frontend_url'] . 'rest/V1/modules', [], CurlInterface::GET); $response = json_decode($this->read(), true); return (null !== $response) && !isset($response['message']); @@ -235,18 +219,4 @@ public function close() { $this->transport->close(); } - - /** - * Return webapiToken. - * - * @return string - */ - public function getWebapiToken() - { - // Request token if integration is no longer valid - if (!$this->isValidIntegration()) { - $this->init(); - } - return $this->webapiToken; - } } diff --git a/dev/tests/functional/tests/app/Magento/AdvancedPricingImportExport/Test/TestCase/ExportAdvancedPricingTest.php b/dev/tests/functional/tests/app/Magento/AdvancedPricingImportExport/Test/TestCase/ExportAdvancedPricingTest.php index fefe0d2c126e5..c2c684c89d06b 100644 --- a/dev/tests/functional/tests/app/Magento/AdvancedPricingImportExport/Test/TestCase/ExportAdvancedPricingTest.php +++ b/dev/tests/functional/tests/app/Magento/AdvancedPricingImportExport/Test/TestCase/ExportAdvancedPricingTest.php @@ -140,9 +140,9 @@ public function test( if ($website) { $website->persist(); $this->setupCurrencyForCustomWebsite($website, $currencyCustomWebsite); - $this->cron->run(); - $this->cron->run(); } + $this->cron->run(); + $this->cron->run(); $products = $this->prepareProducts($products, $website); $this->cron->run(); $this->cron->run(); @@ -165,7 +165,8 @@ public function test( if (!empty($advancedPricingAttributes)) { $products = [$products[0]]; } - + $this->cron->run(); + $this->cron->run(); return [ 'products' => $products ]; diff --git a/dev/tests/functional/tests/app/Magento/CustomerImportExport/Test/TestCase/ExportCustomerAddressesTest.php b/dev/tests/functional/tests/app/Magento/CustomerImportExport/Test/TestCase/ExportCustomerAddressesTest.php index 6b92891ada2b4..17dfb4fb8cdaf 100644 --- a/dev/tests/functional/tests/app/Magento/CustomerImportExport/Test/TestCase/ExportCustomerAddressesTest.php +++ b/dev/tests/functional/tests/app/Magento/CustomerImportExport/Test/TestCase/ExportCustomerAddressesTest.php @@ -87,7 +87,8 @@ public function test( $exportData->persist(); $this->adminExportIndex->getExportForm()->fill($exportData); $this->adminExportIndex->getFilterExport()->clickContinue(); - + $this->cron->run(); + $this->cron->run(); return [ 'customer' => $customer ]; diff --git a/dev/tests/functional/utils/authenticate.php b/dev/tests/functional/utils/authenticate.php deleted file mode 100644 index 15851f6e8000a..0000000000000 --- a/dev/tests/functional/utils/authenticate.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -/** - * Check if token passed in is a valid auth token. - * - * @param string $token - * @return bool - */ -function authenticate($token) -{ - require_once __DIR__ . '/../../../../app/bootstrap.php'; - - $magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER); - $magentoObjectManager = $magentoObjectManagerFactory->create($_SERVER); - $tokenModel = $magentoObjectManager->get(\Magento\Integration\Model\Oauth\Token::class); - - $tokenPassedIn = $token; - // Token returned will be null if the token we passed in is invalid - $tokenFromMagento = $tokenModel->loadByToken($tokenPassedIn)->getToken(); - if (!empty($tokenFromMagento) && ($tokenFromMagento == $tokenPassedIn)) { - return true; - } else { - return false; - } -} diff --git a/dev/tests/functional/utils/command.php b/dev/tests/functional/utils/command.php index 4e18598a935ad..99025dd1cffcc 100644 --- a/dev/tests/functional/utils/command.php +++ b/dev/tests/functional/utils/command.php @@ -3,25 +3,26 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -include __DIR__ . '/authenticate.php'; + +// phpcs:ignore Magento2.Security.IncludeFile require_once __DIR__ . '/../../../../app/bootstrap.php'; use Symfony\Component\Console\Input\StringInput; use Symfony\Component\Console\Output\NullOutput; -if (!empty($_POST['token']) && !empty($_POST['command'])) { - if (authenticate(urldecode($_POST['token']))) { - $command = urldecode($_POST['command']); - $magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER); - $magentoObjectManager = $magentoObjectManagerFactory->create($_SERVER); - $cli = $magentoObjectManager->create(\Magento\Framework\Console\Cli::class); - $input = new StringInput(escapeshellcmd($command)); - $input->setInteractive(false); - $output = new NullOutput(); - $cli->doRun($input, $output); - } else { - echo "Command not unauthorized."; - } +// phpcs:ignore Magento2.Security.Superglobal +if (isset($_GET['command'])) { + // phpcs:ignore Magento2.Security.Superglobal + $command = urldecode($_GET['command']); + // phpcs:ignore Magento2.Security.Superglobal + $magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER); + // phpcs:ignore Magento2.Security.Superglobal + $magentoObjectManager = $magentoObjectManagerFactory->create($_SERVER); + $cli = $magentoObjectManager->create(\Magento\Framework\Console\Cli::class); + $input = new StringInput($command); + $input->setInteractive(false); + $output = new NullOutput(); + $cli->doRun($input, $output); } else { - echo "'token' or 'command' parameter is not set."; + throw new \InvalidArgumentException("Command GET parameter is not set."); } diff --git a/dev/tests/functional/utils/deleteMagentoGeneratedCode.php b/dev/tests/functional/utils/deleteMagentoGeneratedCode.php index 17e3575c87686..17260bd1da635 100644 --- a/dev/tests/functional/utils/deleteMagentoGeneratedCode.php +++ b/dev/tests/functional/utils/deleteMagentoGeneratedCode.php @@ -3,14 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -include __DIR__ . '/authenticate.php'; -if (!empty($_POST['token']) && !empty($_POST['path'])) { - if (authenticate(urldecode($_POST['token']))) { - exec('rm -rf ../../../../generated/*'); - } else { - echo "Command not unauthorized."; - } -} else { - echo "'token' parameter is not set."; -} +// phpcs:ignore Magento2.Security.InsecureFunction +exec('rm -rf ../../../../generated/*'); diff --git a/dev/tests/functional/utils/export.php b/dev/tests/functional/utils/export.php index e3eff6e3fec17..fa50bc729d0f6 100644 --- a/dev/tests/functional/utils/export.php +++ b/dev/tests/functional/utils/export.php @@ -3,30 +3,32 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -include __DIR__ . '/authenticate.php'; -if (!empty($_POST['token']) && !empty($_POST['template'])) { - if (authenticate(urldecode($_POST['token']))) { - $varDir = '../../../../var/export/'; - $template = urldecode($_POST['template']); - $fileList = scandir($varDir, SCANDIR_SORT_NONE); - $files = []; +// phpcs:ignore Magento2.Security.Superglobal +if (!isset($_GET['template'])) { + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \InvalidArgumentException('Argument "template" must be set.'); +} - foreach ($fileList as $fileName) { - if (preg_match("`$template`", $fileName) === 1) { - $filePath = $varDir . $fileName; - $files[] = [ - 'content' => file_get_contents($filePath), - 'name' => $fileName, - 'date' => filectime($filePath), - ]; - } - } +$varDir = '../../../../var/export/'; +// phpcs:ignore Magento2.Security.Superglobal +$template = urldecode($_GET['template']); +// phpcs:ignore Magento2.Functions.DiscouragedFunction +$fileList = scandir($varDir, SCANDIR_SORT_NONE); +$files = []; - echo serialize($files); - } else { - echo "Command not unauthorized."; +foreach ($fileList as $fileName) { + if (preg_match("`$template`", $fileName) === 1) { + $filePath = $varDir . $fileName; + $files[] = [ + // phpcs:ignore Magento2.Functions.DiscouragedFunction + 'content' => file_get_contents($filePath), + 'name' => $fileName, + // phpcs:ignore Magento2.Functions.DiscouragedFunction + 'date' => filectime($filePath), + ]; } -} else { - echo "'token' or 'template' parameter is not set."; } + +// phpcs:ignore Magento2.Security.LanguageConstruct, Magento2.Security.InsecureFunction +echo serialize($files); diff --git a/dev/tests/functional/utils/locales.php b/dev/tests/functional/utils/locales.php index a3b4ec05eed65..11e1e2b70fa50 100644 --- a/dev/tests/functional/utils/locales.php +++ b/dev/tests/functional/utils/locales.php @@ -3,23 +3,20 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -include __DIR__ . '/authenticate.php'; -if (!empty($_POST['token'])) { - if (authenticate(urldecode($_POST['token']))) { - if ($_POST['type'] == 'deployed') { - $themePath = isset($_POST['theme_path']) ? $_POST['theme_path'] : 'adminhtml/Magento/backend'; - $directory = __DIR__ . '/../../../../pub/static/' . $themePath; - $locales = array_diff(scandir($directory), ['..', '.']); - } else { - require_once __DIR__ . DIRECTORY_SEPARATOR . 'bootstrap.php'; - $localeConfig = $magentoObjectManager->create(\Magento\Framework\Locale\Config::class); - $locales = $localeConfig->getAllowedLocales(); - } - echo implode('|', $locales); - } else { - echo "Command not unauthorized."; - } +// phpcs:ignore Magento2.Security.Superglobal +if (isset($_GET['type']) && $_GET['type'] == 'deployed') { + // phpcs:ignore Magento2.Security.Superglobal + $themePath = isset($_GET['theme_path']) ? $_GET['theme_path'] : 'adminhtml/Magento/backend'; + $directory = __DIR__ . '/../../../../pub/static/' . $themePath; + // phpcs:ignore Magento2.Functions.DiscouragedFunction + $locales = array_diff(scandir($directory), ['..', '.']); } else { - echo "'token' parameter is not set."; + // phpcs:ignore Magento2.Security.IncludeFile + require_once __DIR__ . DIRECTORY_SEPARATOR . 'bootstrap.php'; + $localeConfig = $magentoObjectManager->create(\Magento\Framework\Locale\Config::class); + $locales = $localeConfig->getAllowedLocales(); } + +// phpcs:ignore Magento2.Security.LanguageConstruct +echo implode('|', $locales); diff --git a/dev/tests/functional/utils/log.php b/dev/tests/functional/utils/log.php index 889056bfbdd63..30783ae8e1d28 100644 --- a/dev/tests/functional/utils/log.php +++ b/dev/tests/functional/utils/log.php @@ -3,20 +3,21 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -declare(strict_types=1); -include __DIR__ . '/authenticate.php'; -if (!empty($_POST['token']) && !empty($_POST['name'])) { - if (authenticate(urldecode($_POST['token']))) { - $name = urldecode($_POST['name']); - if (preg_match('/\.\.(\\\|\/)/', $name)) { - throw new \InvalidArgumentException('Invalid log file name'); - } +declare(strict_types=1); +// phpcs:ignore Magento2.Security.Superglobal +if (!isset($_GET['name'])) { + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \InvalidArgumentException( + 'The name of log file is required for getting logs.' + ); +} - echo serialize(file_get_contents('../../../../var/log' . '/' . $name)); - } else { - echo "Command not unauthorized."; - } -} else { - echo "'token' or 'name' parameter is not set."; +// phpcs:ignore Magento2.Security.Superglobal +$name = urldecode($_GET['name']); +if (preg_match('/\.\.(\\\|\/)/', $name)) { + throw new \InvalidArgumentException('Invalid log file name'); } + +// phpcs:ignore Magento2.Security.InsecureFunction, Magento2.Functions.DiscouragedFunction, Magento2.Security.LanguageConstruct +echo serialize(file_get_contents('../../../../var/log' .'/' .$name)); diff --git a/dev/tests/functional/utils/pathChecker.php b/dev/tests/functional/utils/pathChecker.php index b5a2ddb405bde..217cf90af0a56 100644 --- a/dev/tests/functional/utils/pathChecker.php +++ b/dev/tests/functional/utils/pathChecker.php @@ -3,20 +3,20 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -include __DIR__ . '/authenticate.php'; -if (!empty($_POST['token']) && !empty($_POST['path'])) { - if (authenticate(urldecode($_POST['token']))) { - $path = urldecode($_POST['path']); - - if (file_exists('../../../../' . $path)) { - echo 'path exists: true'; - } else { - echo 'path exists: false'; - } +// phpcs:ignore Magento2.Security.Superglobal +if (isset($_GET['path'])) { + // phpcs:ignore Magento2.Security.Superglobal + $path = urldecode($_GET['path']); + // phpcs:ignore Magento2.Functions.DiscouragedFunction + if (file_exists('../../../../' . $path)) { + // phpcs:ignore Magento2.Security.LanguageConstruct + echo 'path exists: true'; } else { - echo "Command not unauthorized."; + // phpcs:ignore Magento2.Security.LanguageConstruct + echo 'path exists: false'; } } else { - echo "'token' or 'path' parameter is not set."; + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \InvalidArgumentException("GET parameter 'path' is not set."); } diff --git a/dev/tests/functional/utils/website.php b/dev/tests/functional/utils/website.php index ab8e3742f55ae..720b4962aedd4 100644 --- a/dev/tests/functional/utils/website.php +++ b/dev/tests/functional/utils/website.php @@ -3,35 +3,36 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -include __DIR__ . '/authenticate.php'; -if (!empty($_POST['token']) && !empty($_POST['website_code'])) { - if (authenticate(urldecode($_POST['token']))) { - $websiteCode = urldecode($_POST['website_code']); - $rootDir = '../../../../'; - $websiteDir = $rootDir . 'websites/' . $websiteCode . '/'; - $contents = file_get_contents($rootDir . 'index.php'); +// phpcs:ignore Magento2.Security.Superglobal +if (!isset($_GET['website_code'])) { + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \Exception("website_code GET parameter is not set."); +} + +// phpcs:ignore Magento2.Security.Superglobal +$websiteCode = urldecode($_GET['website_code']); +$rootDir = '../../../../'; +$websiteDir = $rootDir . 'websites/' . $websiteCode . '/'; +// phpcs:ignore Magento2.Functions.DiscouragedFunction +$contents = file_get_contents($rootDir . 'index.php'); - $websiteParam = <<<EOD +$websiteParam = <<<EOD \$params = \$_SERVER; \$params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE] = '$websiteCode'; \$params[\Magento\Store\Model\StoreManager::PARAM_RUN_TYPE] = 'website'; EOD; - $pattern = '`(try {.*?)(\/app\/bootstrap.*?}\n)(.*?)\$_SERVER`mis'; - $replacement = "$1/../..$2\n$websiteParam$3\$params"; +$pattern = '`(try {.*?)(\/app\/bootstrap.*?}\n)(.*?)\$_SERVER`mis'; +$replacement = "$1/../..$2\n$websiteParam$3\$params"; - $contents = preg_replace($pattern, $replacement, $contents); +$contents = preg_replace($pattern, $replacement, $contents); - $old = umask(0); - mkdir($websiteDir, 0760, true); - umask($old); - - copy($rootDir . '.htaccess', $websiteDir . '.htaccess'); - file_put_contents($websiteDir . 'index.php', $contents); - } else { - echo "Command not unauthorized."; - } -} else { - echo "'token' or 'website_code' parameter is not set."; -} +$old = umask(0); +// phpcs:ignore Magento2.Functions.DiscouragedFunction +mkdir($websiteDir, 0760, true); +umask($old); +// phpcs:ignore Magento2.Functions.DiscouragedFunction +copy($rootDir . '.htaccess', $websiteDir . '.htaccess'); +// phpcs:ignore Magento2.Functions.DiscouragedFunction +file_put_contents($websiteDir . 'index.php', $contents); From aa378d608f383d6804965dcac930521d16b7b0b1 Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Thu, 18 Apr 2019 14:12:39 -0500 Subject: [PATCH 566/603] MAGETWO-99022: Braintree Displaying Incorrect Ship-To Name - Fixed unit test --- .../Test/Unit/Controller/Paypal/ReviewTest.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/ReviewTest.php b/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/ReviewTest.php index 609b7f21dbf87..d68838bafbf0e 100644 --- a/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/ReviewTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/ReviewTest.php @@ -6,6 +6,7 @@ namespace Magento\Braintree\Test\Unit\Controller\Paypal; +use Magento\Payment\Model\Method\Logger; use Magento\Quote\Model\Quote; use Magento\Framework\View\Layout; use Magento\Checkout\Model\Session; @@ -65,6 +66,11 @@ class ReviewTest extends \PHPUnit\Framework\TestCase */ private $review; + /** + * @var Logger|\PHPUnit_Framework_MockObject_MockObject + */ + private $loggerMock; + protected function setUp() { /** @var Context|\PHPUnit_Framework_MockObject_MockObject $contextMock */ @@ -88,6 +94,9 @@ protected function setUp() ->getMock(); $this->messageManagerMock = $this->getMockBuilder(ManagerInterface::class) ->getMockForAbstractClass(); + $this->loggerMock = $this->getMockBuilder(Logger::class) + ->disableOriginalConstructor() + ->getMock(); $contextMock->expects(self::once()) ->method('getRequest') @@ -103,7 +112,8 @@ protected function setUp() $contextMock, $this->configMock, $this->checkoutSessionMock, - $this->quoteUpdaterMock + $this->quoteUpdaterMock, + $this->loggerMock ); } From e2cb7364680f55a8160bf455a15397ce79cf2cc1 Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Thu, 18 Apr 2019 14:14:02 -0500 Subject: [PATCH 567/603] MAGETWO-99091: Name of categories in the Category tree on Product Edit page is not displayed according to the selected store view scope - Fixed returnable method type --- .../Ui/DataProvider/Product/Form/Modifier/Categories.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php index db80d110e123a..800ead0e4030c 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php @@ -395,10 +395,10 @@ private function retrieveShownCategoriesIds(int $storeId, string $filter = '') : * * @param int $storeId * @param array $shownCategoriesIds - * @return array + * @return array|null * @throws LocalizedException */ - private function retrieveCategoriesTree(int $storeId, array $shownCategoriesIds) : array + private function retrieveCategoriesTree(int $storeId, array $shownCategoriesIds) : ?array { /* @var $collection \Magento\Catalog\Model\ResourceModel\Category\Collection */ $collection = $this->categoryCollectionFactory->create(); From fe547079fddbb6f15182e2f1b9d13cc8602fc969 Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Thu, 18 Apr 2019 16:12:23 -0500 Subject: [PATCH 568/603] MC-15922: Skip 'Get Category List by category_id' scenario from benchmark --- setup/performance-toolkit/benchmark.jmx | 65 ------------------------- 1 file changed, 65 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 50fdd7462b254..55cdf7379cc5e 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -42802,71 +42802,6 @@ vars.putObject("category", categories[number]); <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/extract_category_setup.jmx</stringProp></JSR223Sampler> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Category List by category_id" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"> - {"query":"query categoryList($id: Int!) {\n category(id: $id) {\n id\n children {\n id\n name\n url_key\n url_path\n children_count\n path\n image\n productImagePreview: products(pageSize: 1) {\n items {\n small_image {\n label\n url\n }\n }\n }\n }\n }\n}","variables":{"id":${category_id}},"operationName":"categoryList"} - </stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_category_list_by_category_id.jmx</stringProp></HTTPSamplerProxy> - <hashTree> - <JSR223Assertion guiclass="TestBeanGUI" testclass="JSR223Assertion" testname="Assert found categories" enabled="true"> - <stringProp name="scriptLanguage">javascript</stringProp> - <stringProp name="parameters"/> - <stringProp name="filename"/> - <stringProp name="cacheKey"/> - <stringProp name="script">var category = vars.getObject("category"); -var response = JSON.parse(prev.getResponseDataAsString()); - -assertCategoryId(category, response); -assertCategoryChildren(category, response); - -function assertCategoryId(category, response) { - if (response.data == undefined || response.data.category == undefined || response.data.category.id != category.id) { - AssertionResult.setFailureMessage("Cannot find category with id \"" + category.id + "\""); - AssertionResult.setFailure(true); - } -} - -function assertCategoryChildren(category, response) { - foundCategory = response.data && response.data.category ? response.data.category : null; - if (foundCategory) { - var childrenFound = foundCategory.children.map(function (c) {return parseInt(c.id)}); - var children = category.children.map(function (c) {return parseInt(c)}); - if (JSON.stringify(children.sort()) != JSON.stringify(childrenFound.sort())) { - AssertionResult.setFailureMessage("Cannot math children categories \"" + JSON.stringify(children) + "\" for to found one: \"" + JSON.stringify(childrenFound) + "\""); - AssertionResult.setFailure(true); - } - } - -} - -</stringProp> - </JSR223Assertion> - <hashTree/> - </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Navigation Menu by category_id" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> From 8a3f00a07ba3b95d96a1589975b9bcec04a7aa88 Mon Sep 17 00:00:00 2001 From: Joan He <johe@magento.com> Date: Thu, 18 Apr 2019 16:14:56 -0500 Subject: [PATCH 569/603] MC-15873: Catch unserializer exception --- .../Model/Config/Backend/Serialized.php | 19 ++++++++++++++- .../Model/Config/Backend/SerializedTest.php | 24 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Config/Model/Config/Backend/Serialized.php b/app/code/Magento/Config/Model/Config/Backend/Serialized.php index 3d5713357c39c..6e0b6275db836 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Serialized.php +++ b/app/code/Magento/Config/Model/Config/Backend/Serialized.php @@ -9,6 +9,8 @@ use Magento\Framework\Serialize\Serializer\Json; /** + * Serialized backend model + * * @api * @since 100.0.2 */ @@ -46,17 +48,32 @@ public function __construct( } /** + * Processing object after load data + * * @return void */ protected function _afterLoad() { $value = $this->getValue(); if (!is_array($value)) { - $this->setValue(empty($value) ? false : $this->serializer->unserialize($value)); + try { + $this->setValue(empty($value) ? false : $this->serializer->unserialize($value)); + } catch (\Exception $e) { + $this->_logger->critical( + sprintf( + 'Failed to unserialize %s config value. The error is: %s', + $this->getPath(), + $e->getMessage() + ) + ); + $this->setValue(false); + } } } /** + * Processing object before save data + * * @return $this */ public function beforeSave() diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/Backend/SerializedTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/Backend/SerializedTest.php index bb1e0e0225901..c2685e0a265cd 100644 --- a/app/code/Magento/Config/Test/Unit/Model/Config/Backend/SerializedTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/Config/Backend/SerializedTest.php @@ -9,7 +9,11 @@ use Magento\Framework\Model\Context; use Magento\Framework\Serialize\Serializer\Json; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Psr\Log\LoggerInterface; +/** + * Class SerializedTest + */ class SerializedTest extends \PHPUnit\Framework\TestCase { /** @var \Magento\Config\Model\Config\Backend\Serialized */ @@ -18,14 +22,20 @@ class SerializedTest extends \PHPUnit\Framework\TestCase /** @var Json|\PHPUnit_Framework_MockObject_MockObject */ private $serializerMock; + /** @var LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $loggerMock; + protected function setUp() { $objectManager = new ObjectManager($this); $this->serializerMock = $this->createMock(Json::class); + $this->loggerMock = $this->createMock(LoggerInterface::class); $contextMock = $this->createMock(Context::class); $eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); $contextMock->method('getEventDispatcher') ->willReturn($eventManagerMock); + $contextMock->method('getLogger') + ->willReturn($this->loggerMock); $this->serializedConfig = $objectManager->getObject( Serialized::class, [ @@ -72,6 +82,20 @@ public function afterLoadDataProvider() ]; } + public function testAfterLoadWithException() + { + $value = '{"key":'; + $expected = false; + $this->serializedConfig->setValue($value); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->willThrowException(new \Exception()); + $this->loggerMock->expects($this->once()) + ->method('critical'); + $this->serializedConfig->afterLoad(); + $this->assertEquals($expected, $this->serializedConfig->getValue()); + } + /** * @param string $expected * @param int|double|string|array|boolean|null $value From f7b6040e7e02f78476da87cd299341b75d73eec5 Mon Sep 17 00:00:00 2001 From: Nikita Fomin <fmnnkt@gmail.com> Date: Fri, 19 Apr 2019 10:08:56 +0300 Subject: [PATCH 570/603] MC-11941: Delete Product Attribute --- .../ProductAttribute/DeleteProductAttributeEntityTest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.xml index 11ba7266ce564..0dd47942c8fe0 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.xml @@ -16,7 +16,6 @@ <constraint name="Magento\ImportExport\Test\Constraint\AssertProductAttributeAbsenceForExport" /> </variation> <variation name="DeleteProductAttributeEntityTestVariation2"> - <data name="tag" xsi:type="string">stable:no</data> <data name="attribute/dataset" xsi:type="string">attribute_type_dropdown</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeSuccessDeleteMessage" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeAbsenceInGrid" /> From c3c2a005b7bc0edbf0cb04e7b1c0fde7d74d5642 Mon Sep 17 00:00:00 2001 From: Ansari <ziyaurrahman@krishtechnolabs.com> Date: Fri, 19 Apr 2019 12:55:29 +0530 Subject: [PATCH 571/603] Spelling correction --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b86c7b79a0cbd..f30c2c64e06fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4335,7 +4335,7 @@ Tests: * Fixed order placing with virtual product using Express Checkout * Fixed the error during order placement with Recurring profile payment * Fixed wrong redirect after customer registration during multishipping checkout - * Fixed inability to crate shipping labels + * Fixed inability to create shipping labels * Fixed inability to switch language, if the default language is English * Fixed an issue with incorrect XML appearing in cache after some actions on the frontend * Fixed product export From 9f994f5c783ad5403a750f54abde9553829b6b8b Mon Sep 17 00:00:00 2001 From: Nikita Fomin <fmnnkt@gmail.com> Date: Fri, 19 Apr 2019 11:19:49 +0300 Subject: [PATCH 572/603] MC-11936: Update Product Attribute --- .../ProductAttribute/UpdateProductAttributeEntityTest.php | 1 - .../ProductAttribute/UpdateProductAttributeEntityTest.xml | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php index 6203f304540c1..b714c61f70198 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php @@ -34,7 +34,6 @@ class UpdateProductAttributeEntityTest extends Injectable { /* tags */ - const MVP = 'yes'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.xml index 40cf8e40ae33f..d6420ff431ce6 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.xml @@ -8,7 +8,6 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\UpdateProductAttributeEntityTest" summary="Update Product Attribute" ticketId="MAGETWO-23459"> <variation name="UpdateProductAttributeEntityTestVariation1"> - <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttributeOriginal/dataset" xsi:type="string">attribute_type_text_field</data> <data name="attribute/data/frontend_label" xsi:type="string">Text_Field_%isolation%</data> @@ -29,7 +28,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" /> </variation> <variation name="UpdateProductAttributeEntityTestVariation2"> - <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttributeOriginal/dataset" xsi:type="string">attribute_type_dropdown</data> <data name="attribute/data/frontend_label" xsi:type="string">Dropdown_%isolation%</data> @@ -55,6 +53,8 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" /> </variation> <variation name="UpdateProductAttributeEntityTestVariation3"> + <data name="issue" xsi:type="string">MAGETWO-46494: [FT] UpdateProductAttributeEntityTestVariation3 does not actually create an attribute to check</data> + <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttributeOriginal/dataset" xsi:type="string">tax_class_id</data> <data name="attribute/data/is_searchable" xsi:type="string">Yes</data> @@ -62,7 +62,6 @@ <data name="cacheTags" xsi:type="array"> <item name="0" xsi:type="string">FPC</item> </data> - <data name="tag" xsi:type="string">to_maintain:yes</data> <constraint name="Magento\PageCache\Test\Constraint\AssertCacheIsRefreshableAndInvalidated" /> <constraint name="Magento\CatalogSearch\Test\Constraint\AssertAdvancedSearchProductByAttribute" /> </variation> From a168a3e1a618c967314fc27a556303530dfd2c26 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 19 Apr 2019 13:57:01 +0300 Subject: [PATCH 573/603] Fix static tests. --- .../Eav/Model/Entity/Attribute/Source/AbstractSource.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php index b291b7b28d5b7..a81d437acea36 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model\Entity\Attribute\Source; /** @@ -65,7 +66,7 @@ public function getOptionText($value) { $options = $this->getAllOptions(); // Fixed for tax_class_id and custom_design - if (sizeof($options) > 0) { + if (count($options) > 0) { foreach ($options as $option) { if (isset($option['value']) && $option['value'] == $value) { return isset($option['label']) ? $option['label'] : $option['value']; @@ -168,10 +169,11 @@ public function toOptionArray() } /** - * Multibyte support strcasecmp function version + * Multibyte support strcasecmp function version. + * * @param string $str1 * @param string $str2 - * @return int|\\lt + * @return int */ private function mbStrcasecmp($str1, $str2) { From aeaff53ca08850ecf6e2b97580810190ddad9087 Mon Sep 17 00:00:00 2001 From: YaroslavHolovanych <yaroslavh@gmail.com> Date: Fri, 19 Apr 2019 14:30:25 +0300 Subject: [PATCH 574/603] MC-11937: Add Products to Shopping Cart --- .../Test/TestCase/AddProductsToShoppingCartEntityTest.xml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml index 8d054c0230873..c0df4b16b92e6 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml @@ -22,7 +22,6 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation2"> - <data name="tag" xsi:type="string">to_maintain:yes, severity:S2</data> <data name="productsData/0" xsi:type="string">bundleProduct::bundle_fixed_product</data> <data name="cart/data/grand_total" xsi:type="string">761</data> <data name="cart/data/subtotal" xsi:type="string">756</data> @@ -35,7 +34,6 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation3"> - <data name="tag" xsi:type="string">to_maintain:yes, severity:S0</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::with_two_custom_option</data> <data name="cart/data/grand_total" xsi:type="string">345</data> <data name="cart/data/subtotal" xsi:type="string">340</data> @@ -48,7 +46,6 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation4"> - <data name="tag" xsi:type="string">to_maintain:yes, severity:S1</data> <data name="productsData/0" xsi:type="string">catalogProductVirtual::product_50_dollar</data> <data name="cart/data/grand_total" xsi:type="string">50</data> <data name="cart/data/subtotal" xsi:type="string">50</data> @@ -100,8 +97,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation8" summary="Enable https in backend and add products of different types to cart" ticketId="MAGETWO-42677"> - <data name="tag" xsi:type="string">to_maintain:yes, severity:S0</data> - <data name="issue" xsi:type="string">Errors on configuration step. Skipped.</data> + <data name="tag" xsi:type="string">severity:S0</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::with_two_custom_option</data> <data name="productsData/1" xsi:type="string">catalogProductVirtual::product_50_dollar</data> <data name="productsData/2" xsi:type="string">downloadableProduct::with_two_separately_links</data> From 5bc05b22c10927b9ec1f3c12daba8c09e35940b7 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 19 Apr 2019 14:48:04 +0300 Subject: [PATCH 575/603] Fix static tests. --- .../Magento/Backup/Controller/Adminhtml/Index/Rollback.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php b/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php index 51fa0ef8f65ad..7f450e7e313cc 100644 --- a/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php +++ b/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php @@ -6,13 +6,16 @@ */ namespace Magento\Backup\Controller\Adminhtml\Index; +use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem; /** + * Backup rollback controller. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Rollback extends \Magento\Backup\Controller\Adminhtml\Index +class Rollback extends \Magento\Backup\Controller\Adminhtml\Index implements HttpPostActionInterface { /** * Rollback Action @@ -124,6 +127,7 @@ public function execute() $adminSession->destroy(); $response->setRedirectUrl($this->getUrl('*')); + // phpcs:disable Magento2.Exceptions.ThrowCatch } catch (\Magento\Framework\Backup\Exception\CantLoadSnapshot $e) { $errorMsg = __('We can\'t find the backup file.'); } catch (\Magento\Framework\Backup\Exception\FtpConnectionFailed $e) { From 651f1d9a0252c6dcafb20e98b4f8b54c3d441281 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 19 Apr 2019 15:08:57 +0300 Subject: [PATCH 576/603] Fix static tests. --- .../Magento/Catalog/Model/Product/Gallery/CreateHandler.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php index d6416a024c6df..d2ad6748a9f83 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php @@ -420,6 +420,7 @@ protected function copyImage($file) $destinationFile = $this->getUniqueFileName($file); if (!$this->mediaDirectory->isFile($this->mediaConfig->getMediaPath($file))) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception(); } @@ -437,6 +438,7 @@ protected function copyImage($file) } return str_replace('\\', '/', $destinationFile); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (\Exception $e) { $file = $this->mediaConfig->getMediaPath($file); throw new \Magento\Framework\Exception\LocalizedException( From ce4c1e3508363258c17267450eab0bfe9bf70ca6 Mon Sep 17 00:00:00 2001 From: Nikita Fomin <fmnnkt@gmail.com> Date: Fri, 19 Apr 2019 15:47:24 +0300 Subject: [PATCH 577/603] MC-11936: Update Product Attribute --- .../ProductAttribute/UpdateProductAttributeEntityTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php index b714c61f70198..6203f304540c1 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php @@ -34,6 +34,7 @@ class UpdateProductAttributeEntityTest extends Injectable { /* tags */ + const MVP = 'yes'; /* end tags */ /** From b6784b5fab4d6d2b4fdf826b96b8a42b202dc631 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 19 Apr 2019 16:24:52 +0300 Subject: [PATCH 578/603] magento/magento2#22382: Static test fix. --- .../Magento/CatalogImportExport/Model/Import/Product.php | 6 +++++- .../CatalogImportExport/Model/Import/ProductTest.php | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index c6ce3e24ce02f..edeb955b19c9b 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -1247,6 +1247,7 @@ protected function _prepareRowForDb(array $rowData) * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * phpcs:disable Generic.Metrics.NestingLevel */ protected function _saveLinks() { @@ -1256,7 +1257,7 @@ protected function _saveLinks() $nextLinkId = $this->_resourceHelper->getNextAutoincrement($mainTable); // pre-load 'position' attributes ID for each link type once - foreach ($this->_linkNameToId as $linkName => $linkId) { + foreach ($this->_linkNameToId as $linkId) { $select = $this->_connection->select()->from( $resource->getTable('catalog_product_link_attribute'), ['id' => 'product_link_attribute_id'] @@ -1374,6 +1375,7 @@ protected function _saveLinks() } return $this; } + // phpcs:enable /** * Save product attributes. @@ -1608,6 +1610,7 @@ public function getImagesFromRow(array $rowData) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * @SuppressWarnings(PHPMD.UnusedLocalVariable) * @throws LocalizedException + * phpcs:disable Generic.Metrics.NestingLevel */ protected function _saveProducts() { @@ -1980,6 +1983,7 @@ protected function _saveProducts() return $this; } + // phpcs:enable /** * Prepare array with image states (visible or hidden from product page) 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 dd2237d6080ca..ceffbc6d138e5 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -34,6 +34,7 @@ * @magentoDataFixtureBeforeTransaction Magento/Catalog/_files/enable_catalog_product_reindex_schedule.php * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * phpcs:disable Generic.PHP.NoSilencedErrors, Generic.Metrics.NestingLevel, Magento2.Functions.StaticFunction */ class ProductTest extends \Magento\TestFramework\Indexer\TestCase { @@ -1820,6 +1821,7 @@ function (ProductInterface $item) { if ($product->getId()) { $productRepository->delete($product); } + // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { //Product already removed } From ab443a09123d90f615e447fef58e5ba6ab22dead Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Thu, 18 Apr 2019 15:08:19 +0300 Subject: [PATCH 579/603] Fix undeclared variables. --- app/code/Magento/Rule/view/adminhtml/web/rules.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Rule/view/adminhtml/web/rules.js b/app/code/Magento/Rule/view/adminhtml/web/rules.js index a15caa08cc0ae..95175d272f9af 100644 --- a/app/code/Magento/Rule/view/adminhtml/web/rules.js +++ b/app/code/Magento/Rule/view/adminhtml/web/rules.js @@ -126,7 +126,7 @@ define([ var values = this.updateElement.value.split(','), s = ''; - for (i = 0; i < values.length; i++) { + for (var i = 0; i < values.length; i++) { s = values[i].strip(); if (s != '') { @@ -255,7 +255,7 @@ define([ if (elem && elem.options) { var selectedOptions = []; - for (i = 0; i < elem.options.length; i++) { + for (var i = 0; i < elem.options.length; i++) { if (elem.options[i].selected) { selectedOptions.push(elem.options[i].text); } From 827c51e53f6d79627a7b4b9f71bcbfba4730d80d Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@magento.com> Date: Fri, 19 Apr 2019 09:36:05 -0500 Subject: [PATCH 580/603] magento-engcom/magento2ce#2771: Fixed code style issues --- .../Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php | 2 +- lib/internal/Magento/Framework/App/Http.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php index 2c32a74eb0f1d..e6c098ab0254e 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableBuilder.php @@ -115,7 +115,7 @@ public function build($storeId, $changedIds, $valueFieldSuffix) /** * Create empty temporary table with given columns list * - * @param string $tableName Table name + * @param string $tableName Table name * @param array $columns array('columnName' => \Magento\Catalog\Model\ResourceModel\Eav\Attribute, ...) * @param string $valueFieldSuffix * diff --git a/lib/internal/Magento/Framework/App/Http.php b/lib/internal/Magento/Framework/App/Http.php index 3564e5e0ecb9b..ca3976da1df52 100644 --- a/lib/internal/Magento/Framework/App/Http.php +++ b/lib/internal/Magento/Framework/App/Http.php @@ -277,7 +277,7 @@ private function redirectToSetup(Bootstrap $bootstrap, \Exception $exception) * Handler for bootstrap errors * * @param Bootstrap $bootstrap - * @param \Exception &$exception + * @param \Exception $exception * @return bool */ private function handleBootstrapErrors(Bootstrap $bootstrap, \Exception &$exception) From bc8efd2c46924888080186b30ecdcc435333074c Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 19 Apr 2019 11:05:47 -0500 Subject: [PATCH 581/603] Minor fixes for magento/magento-functional-tests-migration#387: Convert ResetUserPasswordFailedTest to MFTF --- .../AssertMessageOnAdminLoginActionGroup.xml | 2 ++ .../Backend/Test/Mftf/Page/AdminLoginPage.xml | 2 +- .../Mftf/Section/AdminLoginFormSection.xml | 2 +- .../Section/AdminUserLoginMessagesSection.xml | 15 --------------- .../Test/AdminResetUserPasswordFailedTest.xml | 19 +++++++++++++++++++ ...AssertAdminLoginPageMessageActionGroup.xml | 19 ------------------- .../Test/AdminResetUserPasswordFailedTest.xml | 10 ++-------- 7 files changed, 25 insertions(+), 44 deletions(-) delete mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminUserLoginMessagesSection.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml delete mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminLoginActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminLoginActionGroup.xml index ccc7cd24350c5..607fba3736c42 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminLoginActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminLoginActionGroup.xml @@ -13,6 +13,8 @@ <argument name="message" type="string" defaultValue="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." /> <argument name="messageType" type="string" defaultValue="error" /> </arguments> + + <waitForElementVisible selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" stepKey="waitForAdminLoginFormMessage" /> <see userInput="{{message}}" selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" stepKey="verifyMessage" /> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Page/AdminLoginPage.xml b/app/code/Magento/Backend/Test/Mftf/Page/AdminLoginPage.xml index a499c8f5ed7a7..78226d79273d9 100644 --- a/app/code/Magento/Backend/Test/Mftf/Page/AdminLoginPage.xml +++ b/app/code/Magento/Backend/Test/Mftf/Page/AdminLoginPage.xml @@ -9,7 +9,7 @@ <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> <page name="AdminLoginPage" url="admin" area="admin" module="Magento_Backend"> - <section name="AdminUserLoginMessagesSection"/> + <section name="AdminLoginMessagesSection"/> <section name="AdminLoginFormSection"/> </page> </pages> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml index 9092ef31bbdca..bd65dea89abc2 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml @@ -12,6 +12,6 @@ <element name="username" type="input" selector="#username"/> <element name="password" type="input" selector="#login"/> <element name="signIn" type="button" selector=".actions .action-primary" timeout="30"/> - <element name="forgotPasswordLink" type="link" selector=".action-forgotpassword" timeout="10"/> + <element name="forgotPasswordLink" type="button" selector=".action-forgotpassword" timeout="10"/> </section> </sections> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminUserLoginMessagesSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminUserLoginMessagesSection.xml deleted file mode 100644 index 209a795dc48ae..0000000000000 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminUserLoginMessagesSection.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?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="AdminUserLoginMessagesSection"> - <element name="successMessage" type="text" selector=".message-success"/> - <element name="errorMessage" type="text" selector=".message-error"/> - </section> -</sections> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml new file mode 100644 index 0000000000000..8f9c5828e2f5e --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml @@ -0,0 +1,19 @@ +<?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="AdminResetUserPasswordFailedTest"> + <before> + <magentoCLI command="config:set {{AdminCaptchaDisableConfigData.path}} {{AdminCaptchaDisableConfigData.value}} " stepKey="disableAdminCaptcha"/> + </before> + <after> + <magentoCLI command="config:set {{AdminCaptchaEnableConfigData.path}} {{AdminCaptchaEnableConfigData.value}} " stepKey="enableAdminCaptcha"/> + </after> + </test> +</tests> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.xml deleted file mode 100644 index 5535d2314a69f..0000000000000 --- a/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminLoginPageMessageActionGroup.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"> - <actionGroup name="AssertAdminLoginPageMessageActionGroup"> - <arguments> - <argument name="messageType" type="string"/> - <argument name="message" type="string"/> - </arguments> - - <waitForElementVisible selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" stepKey="waitForAdminLoginFormMessage" /> - <see userInput="{{message}}" selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" stepKey="seeAdminLoginFormMessage"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml index 0d66ed38d4310..e3889b7396a2c 100644 --- a/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml +++ b/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml @@ -16,12 +16,6 @@ <group value="security"/> <group value="mtf_migrated"/> </annotations> - <before> - <magentoCLI command="config:set {{AdminCaptchaDisableConfigData.path}} {{AdminCaptchaDisableConfigData.value}} " stepKey="disableAdminCaptcha"/> - </before> - <after> - <magentoCLI command="config:set {{AdminCaptchaEnableConfigData.path}} {{AdminCaptchaEnableConfigData.value}} " stepKey="enableAdminCaptcha"/> - </after> <!-- First attempt to reset password --> <actionGroup ref="AdminOpenForgotPasswordPageActionGroup" stepKey="openAdminForgotPasswordPage1"/> @@ -29,7 +23,7 @@ <argument name="email" value="customer@example.com"/> </actionGroup> <actionGroup ref="AdminSubmitForgotPasswordFormActionGroup" stepKey="submitAdminForgotPasswordForm1"/> - <actionGroup ref="AssertAdminLoginPageMessageActionGroup" stepKey="seeSuccessMessage"> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeSuccessMessage"> <argument name="messageType" value="success"/> <argument name="message" value="We'll email you a link to reset your password."/> </actionGroup> @@ -40,7 +34,7 @@ <argument name="email" value="customer@example.com"/> </actionGroup> <actionGroup ref="AdminSubmitForgotPasswordFormActionGroup" stepKey="submitAdminForgotPasswordForm2"/> - <actionGroup ref="AssertAdminLoginPageMessageActionGroup" stepKey="seeErrorMessage"> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeErrorMessage"> <argument name="messageType" value="error"/> <argument name="message" value="We received too many requests for password resets. Please wait and try again later or contact hello@example.com."/> </actionGroup> From 3ab170807acf688d3e835075c4be6d6f478336e4 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 19 Apr 2019 11:12:03 -0500 Subject: [PATCH 582/603] Minor fixes for magento/magento-functional-tests-migration#387: Convert ResetUserPasswordFailedTest to MFTF --- .../User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml index e3889b7396a2c..4b48c65a18994 100644 --- a/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml +++ b/app/code/Magento/User/Test/Mftf/Test/AdminResetUserPasswordFailedTest.xml @@ -13,6 +13,7 @@ <features value="User"/> <title value="Admin user should not be able to trigger the password reset procedure twice"/> <description value="Admin user should not be able to trigger the password reset procedure twice"/> + <testCaseId value="MC-14389" /> <group value="security"/> <group value="mtf_migrated"/> </annotations> From 1ec6304f1b03e35229bbae28c957b0790381ac7d Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Fri, 19 Apr 2019 13:06:35 -0500 Subject: [PATCH 583/603] GraphQL-604: [Test coverage] End to tests for customer checkout workflow --- .../Quote/Customer/CheckoutEndToEndTest.php | 530 +++++++++++++++ .../Quote/Customer/CreateEmptyCartTest.php | 34 +- .../Quote/Customer/EndToEndCheckoutTest.php | 623 ------------------ .../GraphQl/Quote/Customer/PlaceOrderTest.php | 1 - .../Quote/Guest/CheckoutEndToEndTest.php | 441 +++++++++++++ .../Quote/Guest/CreateEmptyCartTest.php | 34 +- 6 files changed, 989 insertions(+), 674 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php delete mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php new file mode 100644 index 0000000000000..8592a986c5dce --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -0,0 +1,530 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Framework\Registry; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\ResourceModel\Order\CollectionFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * End to checkout tests for customer + */ +class CheckoutEndToEndTest extends GraphQlAbstract +{ + /** + * @var Registry + */ + private $registry; + + /** + * @var QuoteCollectionFactory + */ + private $quoteCollectionFactory; + + /** + * @var QuoteResource + */ + private $quoteResource; + + /** + * @var QuoteIdMaskFactory + */ + private $quoteIdMaskFactory; + + /** + * @var CustomerRepositoryInterface + */ + private $customerRepository; + + /** + * @var CollectionFactory + */ + private $orderCollectionFactory; + + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + + /** + * @var array + */ + private $headers = []; + + protected function setUp() + { + parent::setUp(); + + $objectManager = Bootstrap::getObjectManager(); + $this->registry = $objectManager->get(Registry::class); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); + $this->quoteResource = $objectManager->get(QuoteResource::class); + $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); + $this->customerRepository = Bootstrap::getObjectManager()->get(CustomerRepositoryInterface::class); + $this->orderCollectionFactory = $objectManager->get(CollectionFactory::class); + $this->orderRepository = $objectManager->get(OrderRepositoryInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php + */ + public function testCheckoutWorkflow() + { + $qty = 2; + + $this->createCustomer(); + $token = $this->loginCustomer(); + $this->headers = ['Authorization' => 'Bearer ' . $token]; + + $sku = $this->findProduct(); + $cartId = $this->createEmptyCart(); + $this->addProductToCart($cartId, $qty, $sku); + + $this->setBillingAddress($cartId); + $shippingAddress = $this->setShippingAddress($cartId); + + $shippingMethod = current($shippingAddress['available_shipping_methods']); + $paymentMethod = $this->setShippingMethod($cartId, $shippingAddress['address_id'], $shippingMethod); + $this->setPaymentMethod($cartId, $paymentMethod); + + $orderId = $this->placeOrder($cartId); + $this->checkOrderInHistory($orderId); + } + + /** + * @return void + */ + private function createCustomer(): void + { + $query = <<<QUERY +mutation { + createCustomer( + input: { + firstname: "endto" + lastname: "endtester" + email: "customer@example.com" + password: "123123Qa" + } + ) { + customer { + id + } + } +} +QUERY; + $this->graphQlMutation($query); + } + + /** + * @return string + */ + private function loginCustomer(): string + { + $query = <<<QUERY +mutation { + generateCustomerToken( + email: "customer@example.com" + password: "123123Qa" + ) { + token + } +} +QUERY; + $response = $this->graphQlMutation($query); + self::assertArrayHasKey('generateCustomerToken', $response); + self::assertArrayHasKey('token', $response['generateCustomerToken']); + self::assertNotEmpty($response['generateCustomerToken']['token']); + + return $response['generateCustomerToken']['token']; + } + + /** + * @return string + */ + private function findProduct(): string + { + $query = <<<QUERY +{ + products ( + filter: { + sku: { + like:"simple%" + } + } + pageSize: 1 + currentPage: 1 + ) { + items { + sku + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + self::assertArrayHasKey('products', $response); + self::assertArrayHasKey('items', $response['products']); + self::assertCount(1, $response['products']['items']); + + $product = current($response['products']['items']); + self::assertArrayHasKey('sku', $product); + self::assertNotEmpty($product['sku']); + + return $product['sku']; + } + + /** + * @return string + */ + private function createEmptyCart(): string + { + $query = <<<QUERY +mutation { + createEmptyCart +} +QUERY; + $response = $this->graphQlMutation($query, [], '', $this->headers); + self::assertArrayHasKey('createEmptyCart', $response); + self::assertNotEmpty($response['createEmptyCart']); + + return $response['createEmptyCart']; + } + + /** + * @param string $cartId + * @param float $qty + * @param string $sku + * @return void + */ + private function addProductToCart(string $cartId, float $qty, string $sku): void + { + $query = <<<QUERY +mutation { + addSimpleProductsToCart( + input: { + cart_id: "{$cartId}" + cartItems: [ + { + data: { + qty: {$qty} + sku: "{$sku}" + } + } + ] + } + ) { + cart { + items { + qty + product { + sku + } + } + } + } +} +QUERY; + $this->graphQlMutation($query, [], '', $this->headers); + } + + /** + * @param string $cartId + * @param array $auth + * @return array + */ + private function setBillingAddress(string $cartId): void + { + $query = <<<QUERY +mutation { + setBillingAddressOnCart( + input: { + cart_id: "{$cartId}" + billing_address: { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + city: "test city" + postcode: "887766" + telephone: "88776655" + region: "TX" + country_code: "US" + save_in_address_book: false + } + } + } + ) { + cart { + billing_address { + address_type + } + } + } +} +QUERY; + $this->graphQlMutation($query, [], '', $this->headers); + } + + /** + * @param string $cartId + * @return array + */ + private function setShippingAddress(string $cartId): array + { + $query = <<<QUERY +mutation { + setShippingAddressesOnCart( + input: { + cart_id: "$cartId" + shipping_addresses: [ + { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + city: "test city" + region: "TX" + postcode: "887766" + country_code: "US" + telephone: "88776655" + save_in_address_book: false + } + } + ] + } + ) { + cart { + shipping_addresses { + address_id + available_shipping_methods { + carrier_code + method_code + amount + } + } + } + } +} +QUERY; + $response = $this->graphQlMutation($query, [], '', $this->headers); + self::assertArrayHasKey('setShippingAddressesOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingAddressesOnCart']['cart']); + self::assertCount(1, $response['setShippingAddressesOnCart']['cart']['shipping_addresses']); + + $shippingAddress = current($response['setShippingAddressesOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('address_id', $shippingAddress); + self::assertNotEmpty($shippingAddress['address_id']); + self::assertArrayHasKey('available_shipping_methods', $shippingAddress); + self::assertCount(1, $shippingAddress['available_shipping_methods']); + + $availableShippingMethod = current($shippingAddress['available_shipping_methods']); + self::assertArrayHasKey('carrier_code', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['carrier_code']); + + self::assertArrayHasKey('method_code', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['method_code']); + + self::assertArrayHasKey('amount', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['amount']); + + return $shippingAddress; + } + + /** + * @param string $cartId + * @param int $addressId + * @param array $method + * @return array + */ + private function setShippingMethod(string $cartId, int $addressId, array $method): array + { + $query = <<<QUERY +mutation { + setShippingMethodsOnCart(input: { + cart_id: "{$cartId}", + shipping_methods: [ + { + cart_address_id: {$addressId} + carrier_code: "{$method['carrier_code']}" + method_code: "{$method['method_code']}" + } + ] + }) { + cart { + available_payment_methods { + code + title + } + } + } +} +QUERY; + $response = $this->graphQlMutation($query, [], '', $this->headers); + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('available_payment_methods', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['available_payment_methods']); + + $availablePaymentMethod = current($response['setShippingMethodsOnCart']['cart']['available_payment_methods']); + self::assertArrayHasKey('code', $availablePaymentMethod); + self::assertNotEmpty($availablePaymentMethod['code']); + self::assertArrayHasKey('title', $availablePaymentMethod); + self::assertNotEmpty($availablePaymentMethod['title']); + + return $availablePaymentMethod; + } + + /** + * @param string $cartId + * @param array $method + * @return void + */ + private function setPaymentMethod(string $cartId, array $method): void + { + $query = <<<QUERY +mutation { + setPaymentMethodOnCart( + input: { + cart_id: "{$cartId}" + payment_method: { + code: "{$method['code']}" + } + } + ) { + cart { + selected_payment_method { + code + } + } + } +} +QUERY; + $this->graphQlMutation($query, [], '', $this->headers); + } + + /** + * @param string $cartId + * @return string + */ + private function placeOrder(string $cartId): string + { + $query = <<<QUERY +mutation { + placeOrder( + input: { + cart_id: "{$cartId}" + } + ) { + order { + order_id + } + } +} +QUERY; + $response = $this->graphQlMutation($query, [], '', $this->headers); + self::assertArrayHasKey('placeOrder', $response); + self::assertArrayHasKey('order', $response['placeOrder']); + self::assertArrayHasKey('order_id', $response['placeOrder']['order']); + self::assertNotEmpty($response['placeOrder']['order']['order_id']); + + return $response['placeOrder']['order']['order_id']; + } + + /** + * @param string $orderId + * @return void + */ + private function checkOrderInHistory(string $orderId): void + { + $query = <<<QUERY +{ + customerOrders { + items { + increment_id + grand_total + } + } +} +QUERY; + $response = $this->graphQlQuery($query, [], '', $this->headers); + self::assertArrayHasKey('customerOrders', $response); + self::assertArrayHasKey('items', $response['customerOrders']); + self::assertCount(1, $response['customerOrders']['items']); + + $order = current($response['customerOrders']['items']); + self::assertArrayHasKey('increment_id', $order); + self::assertEquals($orderId, $order['increment_id']); + + self::assertArrayHasKey('grand_total', $order); + } + + public function tearDown() + { + $this->deleteCustomer(); + $this->deleteQuote(); + $this->deleteOrder(); + parent::tearDown(); + } + + /** + * @return void + */ + private function deleteCustomer(): void + { + $email = 'customer@example.com'; + try { + $customer = $this->customerRepository->get($email); + } catch (\Exception $exception) { + return; + } + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', true); + $this->customerRepository->delete($customer); + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', false); + } + + /** + * @return void + */ + private function deleteQuote(): void + { + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { + $this->quoteResource->delete($quote); + + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $quoteIdMask->setQuoteId($quote->getId()) + ->delete(); + } + } + + /** + * @return void + */ + private function deleteOrder() + { + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', true); + + $orderCollection = $this->orderCollectionFactory->create(); + foreach ($orderCollection as $order) { + $this->orderRepository->delete($order); + } + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', false); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php index fc66e4647e576..56ef78811dd1f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php @@ -8,9 +8,8 @@ namespace Magento\GraphQl\Quote\Customer; use Magento\Integration\Api\CustomerTokenServiceInterface; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -32,38 +31,27 @@ class CreateEmptyCartTest extends GraphQlAbstract private $customerTokenService; /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var QuoteFactory + * @var QuoteCollectionFactory */ - private $quoteFactory; + private $quoteCollectionFactory; /** - * @var MaskedQuoteIdToQuoteIdInterface + * @var QuoteResource */ - private $maskedQuoteIdToQuoteId; + private $quoteResource; /** * @var QuoteIdMaskFactory */ private $quoteIdMaskFactory; - /** - * @var string - */ - private $maskedQuoteId; - protected function setUp() { $objectManager = Bootstrap::getObjectManager(); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); $this->guestCartRepository = $objectManager->get(GuestCartRepositoryInterface::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->maskedQuoteIdToQuoteId = $objectManager->get(MaskedQuoteIdToQuoteIdInterface::class); $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); } @@ -79,7 +67,6 @@ public function testCreateEmptyCart() self::assertNotEmpty($response['createEmptyCart']); $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); - $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertEquals(1, $guestCart->getCustomer()->getId()); @@ -138,15 +125,12 @@ private function getHeaderMapWithCustomerToken( public function tearDown() { - if (null !== $this->maskedQuoteId) { - $quoteId = $this->maskedQuoteIdToQuoteId->execute($this->maskedQuoteId); - - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $quoteId); + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { $this->quoteResource->delete($quote); $quoteIdMask = $this->quoteIdMaskFactory->create(); - $quoteIdMask->setQuoteId($quoteId) + $quoteIdMask->setQuoteId($quote->getId()) ->delete(); } parent::tearDown(); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php deleted file mode 100644 index 0354356d6927c..0000000000000 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php +++ /dev/null @@ -1,623 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\GraphQl\Quote\Customer; - -use Magento\TestFramework\TestCase\GraphQlAbstract; - -/** - * End to checkout tests for customers and guests - */ -class EndToEndCheckoutTest extends GraphQlAbstract -{ - /** - * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php - */ - public function testCheckoutAsCustomer() - { - $email = 'e2e_1@example.com'; - - $this->graphQlMutation($this->buildCreateCustomerMutation($email)); - $authHeader = $this->createAuthHeader($email); - - $cartId = $this->createEmptyCart($authHeader); - $cart = $this->configureQuote($cartId, $authHeader); - - $placeOrderResult = $this->graphQlMutation($this->buildPlaceOrderMutation($cartId), [], '', $authHeader); - $orderId = $placeOrderResult['placeOrder']['order']['order_id']; - $this->assertNotEmpty($orderId); - - $order = $this->getOrderFromHistory($orderId, $authHeader); - $this->assertEquals($cart['prices']['grand_total']['value'], $order['grand_total']); - //TODO: Make additional assertions when order properties are added - } - - /** - * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php - */ - public function testCheckoutAsGuest() - { - $email = 'e2e_2@example.com'; - $cartId = $this->createEmptyCart(); - $this->graphQlMutation($this->buildSetGuestEmailOnCartMutation($cartId, $email)); - $this->configureQuote($cartId); - - $placeOrderResult = $this->graphQlMutation($this->buildPlaceOrderMutation($cartId)); - $orderId = $placeOrderResult['placeOrder']['order']['order_id']; - - $this->assertNotEmpty($orderId); - } - - /** - * Configures cart with order placement requirements - * - * @param string $cartId - * @param array $headers - * @return array - */ - private function configureQuote(string $cartId, array $headers = []): array - { - $expectedTotal = 5.99; - $expectedQty = 1; - - $sku = $this->getSku($headers); - $addToCartResult = $this->graphQlMutation($this->buildAddToCartMutation($cartId, $expectedQty, $sku), [], '', $headers); - $cart = $addToCartResult['addSimpleProductsToCart']['cart']; - $this->assertGrandTotal($expectedTotal, $cart); - - $address = $this->setShippingAddress($cartId, $headers); - $shippingMethod = $this->extractFirstAvailableShippingMethod($address); - - $cart = $this->setShippingMethod($cartId, $shippingMethod, $address, $headers); - $expectedTotal += $shippingMethod['amount']; - $this->assertGrandTotal($expectedTotal, $cart); - $this->assertSelectedShippingMethod($shippingMethod, $cart); - - $setBillingAddressResult = $this->graphQlMutation($this->buildSetNewBillingAddressMutation($cartId), [], '', $headers); - $cart = $setBillingAddressResult['setBillingAddressOnCart']['cart']; - $paymentMethod = $this->extractFirstAvailablePaymentMethod($cart); - - $setPaymentResult = $this->graphQlMutation($this->buildSetPaymentMethodMutation($cartId, $paymentMethod), [], '', $headers); - $cart = $setPaymentResult['setPaymentMethodOnCart']['cart']; - $this->assertPaymentMethod($paymentMethod, $cart); - $this->assertGrandTotal($expectedTotal, $cart); - - return $cart; - } - - /** - * Generates customer authentication header for restricted requests - * - * @param string $email - * @return array - */ - private function createAuthHeader(string $email): array - { - $result = $this->graphQlMutation($this->buildLoginMutation($email)); - $token = $result['generateCustomerToken']['token']; - - return ['Authorization' => 'Bearer ' . $token]; - } - - /** - * Creates empty cart for customer or guest - * - * @param array $auth - * @return string - */ - private function createEmptyCart(array $auth = []): string - { - $query = <<<QUERY -mutation { - createEmptyCart -} -QUERY; - - $result = $this->graphQlMutation($query, [], '', $auth); - - return $result['createEmptyCart']; - } - - /** - * Get first SKU returned by catalog search - * - * @param array $auth - * @return string - */ - private function getSku(array $auth): string - { - $result = $this->graphQlQuery($this->buildProductSearchQuery('simple'), [], '', $auth); - $items = $result['products']['items']; - $item = current($items); - - return $item['sku']; - } - - /** - * Set cart shipping address - * - * @param string $cartId - * @param array $auth - * @return array - */ - private function setShippingAddress(string $cartId, array $auth): array - { - $result = $this->graphQlMutation($this->buildSetNewShippingAddressMutation($cartId), [], '', $auth); - $addresses = $result['setShippingAddressesOnCart']['cart']['shipping_addresses']; - - return current($addresses); - } - - /** - * Set cart shipping method - * - * @param string $cartId - * @param array $method - * @param array $address - * @param array $auth - * @return array - */ - private function setShippingMethod(string $cartId, array $method, array $address, array $auth): array - { - $result = $this->graphQlMutation($this->buildSetShippingMethodMutation($cartId, $method, $address), [], '', $auth); - - return $result['setShippingMethodsOnCart']['cart']; - } - - /** - * Get order from history by increment id - * - * @param string $orderId - * @param array $auth - * @return array - */ - private function getOrderFromHistory(string $orderId, array $auth): array - { - $query = <<<QUERY -{ - customerOrders { - items { - increment_id - grand_total - } - } -} -QUERY; - - $result = $this->graphQlQuery($query, [], '', $auth); - $orders = $result['customerOrders']['items']; - - foreach ($orders as $order) { - if ($order['increment_id'] === $orderId) { - return $order; - } - } - - $this->fail(sprintf('No order with increment_id: %s', $orderId)); - } - - /** - * Get first shipping method available from address - * @param array $address - * @return array - */ - private function extractFirstAvailableShippingMethod(array $address): array - { - $methods = $address['available_shipping_methods']; - - return current($methods); - } - - /** - * Get first payment method available from cart - * - * @param array $cart - * @return array - */ - private function extractFirstAvailablePaymentMethod(array $cart): array - { - $methods = $cart['available_payment_methods']; - - return current($methods); - } - - /** - * Assert cart grand total - * - * @param float $expected - * @param array $cart - */ - private function assertGrandTotal(float $expected, array $cart): void - { - $this->assertEquals($expected, $cart['prices']['grand_total']['value']); - } - - /** - * Assert cart payment method - * @param array $method - * @param array $cart - */ - private function assertPaymentMethod(array $method, array $cart): void - { - $this->assertEquals($method['code'], $cart['selected_payment_method']['code']); - } - - /** - * Assert cart shipping method - * - * @param array $expectedMethod - * @param array $cart - */ - private function assertSelectedShippingMethod(array $expectedMethod, array $cart): void - { - $address = current($cart['shipping_addresses']); - $selectedMethod = $address['selected_shipping_method']; - - $this->assertEquals($expectedMethod['carrier_code'], $selectedMethod['carrier_code']); - $this->assertEquals($expectedMethod['method_code'], $selectedMethod['method_code']); - } - - /** - * Build createCustomer mutation - * - * @param string $email - * @return string - */ - private function buildCreateCustomerMutation(string $email): string - { - return <<<QUERY -mutation { - createCustomer( - input: { - firstname: "endto" - lastname: "endtester" - email: "{$email}" - password: "123123Qr" - } - ) { - customer { - id - firstname - lastname - email - } - } -} -QUERY; - } - - /** - * Build generateCustomerToken mutation - * - * @param string $email - * @return string - */ - private function buildLoginMutation(string $email): string - { - return <<<QUERY -mutation { - generateCustomerToken( - email: "{$email}" - password: "123123Qr" - ){ - token - } -} -QUERY; - } - - /** - * Build product search mutation - * - * @param string $term - * @return string - */ - private function buildProductSearchQuery(string $term): string - { - return <<<QUERY -{ - products ( - filter: { - sku: { - like:"{$term}%" - } - } - pageSize: 20 - currentPage: 1 - ) { - items { - sku - } - } -} -QUERY; - } - - /** - * Build addSimpleProductsToCart mutation - * - * @param string $cartId - * @param float $qty - * @param string $sku - * @return string - */ - private function buildAddToCartMutation(string $cartId, float $qty, string $sku): string - { - return <<<QUERY -mutation { - addSimpleProductsToCart( - input: { - cart_id: "{$cartId}" - cartItems: [ - { - data: { - qty: {$qty} - sku: "{$sku}" - } - } - ] - } - ) { - cart { - items { - qty - product { - sku - } - } - prices { - grand_total { - value, - currency - } - } - } - } -} -QUERY; - } - - /** - * Build setShippingAddressesOnCart mutation - * - * @param string $cartId - * @param bool $save - * @return string - */ - private function buildSetNewShippingAddressMutation(string $cartId, bool $save = false): string - { - $save = json_encode($save); - return <<<QUERY -mutation { - setShippingAddressesOnCart( - input: { - cart_id: "$cartId" - shipping_addresses: [ - { - address: { - firstname: "test firstname" - lastname: "test lastname" - company: "test company" - street: ["test street 1", "test street 2"] - city: "test city" - region: "TX" - postcode: "887766" - country_code: "US" - telephone: "88776655" - save_in_address_book: {$save} - } - } - ] - } - ) { - cart { - shipping_addresses { - address_id - available_shipping_methods { - carrier_code - method_code - amount - } - } - } - } -} -QUERY; - } - - /** - * Build setShippingMethodsOnCart mutation - * - * @param string $cartId - * @param array $method - * @param array $address - * @return string - */ - private function buildSetShippingMethodMutation(string $cartId, array $method, array $address): string - { - return <<<QUERY -mutation { - setShippingMethodsOnCart(input: { - cart_id: "{$cartId}", - shipping_methods: [ - { - cart_address_id: {$address['address_id']} - carrier_code: "{$method['carrier_code']}" - method_code: "{$method['method_code']}" - } - ] - }) { - cart { - prices { - grand_total { - value, - currency - } - } - shipping_addresses { - selected_shipping_method { - carrier_code - method_code - } - } - } - } -} -QUERY; - - } - - /** - * Build setBillingAddressOnCart mutation - * - * @param string $cartId - * @param bool $save - * @return string - */ - private function buildSetNewBillingAddressMutation(string $cartId, bool $save = false): string - { - $save = json_encode($save); - return <<<QUERY -mutation { - setBillingAddressOnCart( - input: { - cart_id: "{$cartId}" - billing_address: { - address: { - firstname: "test firstname" - lastname: "test lastname" - street: ["test street 1", "test street 2"] - city: "test city" - region: "TX" - postcode: "887766" - country_code: "US" - telephone: "88776655" - save_in_address_book: {$save} - } - } - } - ) { - cart { - available_payment_methods { - code - title - } - billing_address { - firstname - lastname - company - street - city - postcode - telephone - country { - code - label - } - address_type - } - } - } -} -QUERY; - } - - /** - * Build setPaymentMethodOnCart mutation - * - * @param string $cartId - * @param array $payment - * @return string - */ - private function buildSetPaymentMethodMutation(string $cartId, array $payment): string - { - return <<<QUERY -mutation { - setPaymentMethodOnCart( - input: { - cart_id: "{$cartId}" - payment_method: { - code: "{$payment['code']}" - } - } - ) { - cart { - items { - qty - product { - sku - } - } - shipping_addresses { - selected_shipping_method { - carrier_code - method_code - } - } - selected_payment_method { - code - } - prices { - grand_total { - value - currency - } - } - } - } -} -QUERY; - } - - /** - * Build setGuestEmailOnCart mutation - * - * @param string $cartId - * @param string $email - * @return string - */ - private function buildSetGuestEmailOnCartMutation(string $cartId, string $email): string - { - return <<<QUERY -mutation { - setGuestEmailOnCart( - input: { - cart_id: "{$cartId}" - email: "{$email}" - } - ) { - cart { - email - } - } -} -QUERY; - } - - /** - * Build placeOrder mutation - * - * @param string $cartId - * @return string - */ - private function buildPlaceOrderMutation(string $cartId): string - { - return <<<QUERY -mutation { - placeOrder( - input: { - cart_id: "{$cartId}" - } - ) { - order { - order_id - } - } -} -QUERY; - } -} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php index b7d3b546ba194..47d0d661fb33c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php @@ -7,7 +7,6 @@ namespace Magento\GraphQl\Quote\Customer; -use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Registry; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\Integration\Api\CustomerTokenServiceInterface; diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php new file mode 100644 index 0000000000000..f5114b9253a40 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -0,0 +1,441 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\Framework\Registry; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\ResourceModel\Order\CollectionFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * End to checkout tests for guest + */ +class CheckoutEndToEndTest extends GraphQlAbstract +{ + /** + * @var Registry + */ + private $registry; + + /** + * @var QuoteCollectionFactory + */ + private $quoteCollectionFactory; + + /** + * @var QuoteResource + */ + private $quoteResource; + + /** + * @var QuoteIdMaskFactory + */ + private $quoteIdMaskFactory; + + /** + * @var CollectionFactory + */ + private $orderCollectionFactory; + + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + + protected function setUp() + { + parent::setUp(); + + $objectManager = Bootstrap::getObjectManager(); + $this->registry = $objectManager->get(Registry::class); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); + $this->quoteResource = $objectManager->get(QuoteResource::class); + $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); + $this->orderCollectionFactory = $objectManager->get(CollectionFactory::class); + $this->orderRepository = $objectManager->get(OrderRepositoryInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php + */ + public function testCheckoutWorkflow() + { + $qty = 2; + + $sku = $this->findProduct(); + $cartId = $this->createEmptyCart(); + $this->setGuestEmailOnCart($cartId); + $this->addProductToCart($cartId, $qty, $sku); + + $this->setBillingAddress($cartId); + $shippingAddress = $this->setShippingAddress($cartId); + + $shippingMethod = current($shippingAddress['available_shipping_methods']); + $paymentMethod = $this->setShippingMethod($cartId, $shippingAddress['address_id'], $shippingMethod); + $this->setPaymentMethod($cartId, $paymentMethod); + + $this->placeOrder($cartId); + } + + /** + * @return string + */ + private function findProduct(): string + { + $query = <<<QUERY +{ + products ( + filter: { + sku: { + like:"simple%" + } + } + pageSize: 1 + currentPage: 1 + ) { + items { + sku + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + self::assertArrayHasKey('products', $response); + self::assertArrayHasKey('items', $response['products']); + self::assertCount(1, $response['products']['items']); + + $product = current($response['products']['items']); + self::assertArrayHasKey('sku', $product); + self::assertNotEmpty($product['sku']); + + return $product['sku']; + } + + /** + * @return string + */ + private function createEmptyCart(): string + { + $query = <<<QUERY +mutation { + createEmptyCart +} +QUERY; + $response = $this->graphQlMutation($query); + self::assertArrayHasKey('createEmptyCart', $response); + self::assertNotEmpty($response['createEmptyCart']); + + return $response['createEmptyCart']; + } + + /** + * @param string $cartId + * @return void + */ + private function setGuestEmailOnCart(string $cartId): void + { + $query = <<<QUERY +mutation { + setGuestEmailOnCart( + input: { + cart_id: "{$cartId}" + email: "customer@example.com" + } + ) { + cart { + email + } + } +} +QUERY; + $this->graphQlMutation($query); + } + + /** + * @param string $cartId + * @param float $qty + * @param string $sku + * @return void + */ + private function addProductToCart(string $cartId, float $qty, string $sku): void + { + $query = <<<QUERY +mutation { + addSimpleProductsToCart( + input: { + cart_id: "{$cartId}" + cartItems: [ + { + data: { + qty: {$qty} + sku: "{$sku}" + } + } + ] + } + ) { + cart { + items { + qty + product { + sku + } + } + } + } +} +QUERY; + $this->graphQlMutation($query); + } + + /** + * @param string $cartId + * @param array $auth + * @return array + */ + private function setBillingAddress(string $cartId): void + { + $query = <<<QUERY +mutation { + setBillingAddressOnCart( + input: { + cart_id: "{$cartId}" + billing_address: { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + city: "test city" + postcode: "887766" + telephone: "88776655" + region: "TX" + country_code: "US" + save_in_address_book: false + } + } + } + ) { + cart { + billing_address { + address_type + } + } + } +} +QUERY; + $this->graphQlMutation($query); + } + + /** + * @param string $cartId + * @return array + */ + private function setShippingAddress(string $cartId): array + { + $query = <<<QUERY +mutation { + setShippingAddressesOnCart( + input: { + cart_id: "$cartId" + shipping_addresses: [ + { + address: { + firstname: "test firstname" + lastname: "test lastname" + company: "test company" + street: ["test street 1", "test street 2"] + city: "test city" + region: "TX" + postcode: "887766" + country_code: "US" + telephone: "88776655" + save_in_address_book: false + } + } + ] + } + ) { + cart { + shipping_addresses { + address_id + available_shipping_methods { + carrier_code + method_code + amount + } + } + } + } +} +QUERY; + $response = $this->graphQlMutation($query); + self::assertArrayHasKey('setShippingAddressesOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingAddressesOnCart']['cart']); + self::assertCount(1, $response['setShippingAddressesOnCart']['cart']['shipping_addresses']); + + $shippingAddress = current($response['setShippingAddressesOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('address_id', $shippingAddress); + self::assertNotEmpty($shippingAddress['address_id']); + self::assertArrayHasKey('available_shipping_methods', $shippingAddress); + self::assertCount(1, $shippingAddress['available_shipping_methods']); + + $availableShippingMethod = current($shippingAddress['available_shipping_methods']); + self::assertArrayHasKey('carrier_code', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['carrier_code']); + + self::assertArrayHasKey('method_code', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['method_code']); + + self::assertArrayHasKey('amount', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['amount']); + + return $shippingAddress; + } + + /** + * @param string $cartId + * @param int $addressId + * @param array $method + * @return array + */ + private function setShippingMethod(string $cartId, int $addressId, array $method): array + { + $query = <<<QUERY +mutation { + setShippingMethodsOnCart(input: { + cart_id: "{$cartId}", + shipping_methods: [ + { + cart_address_id: {$addressId} + carrier_code: "{$method['carrier_code']}" + method_code: "{$method['method_code']}" + } + ] + }) { + cart { + available_payment_methods { + code + title + } + } + } +} +QUERY; + $response = $this->graphQlMutation($query); + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('available_payment_methods', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['available_payment_methods']); + + $availablePaymentMethod = current($response['setShippingMethodsOnCart']['cart']['available_payment_methods']); + self::assertArrayHasKey('code', $availablePaymentMethod); + self::assertNotEmpty($availablePaymentMethod['code']); + self::assertArrayHasKey('title', $availablePaymentMethod); + self::assertNotEmpty($availablePaymentMethod['title']); + + return $availablePaymentMethod; + } + + /** + * @param string $cartId + * @param array $method + * @return void + */ + private function setPaymentMethod(string $cartId, array $method): void + { + $query = <<<QUERY +mutation { + setPaymentMethodOnCart( + input: { + cart_id: "{$cartId}" + payment_method: { + code: "{$method['code']}" + } + } + ) { + cart { + selected_payment_method { + code + } + } + } +} +QUERY; + $this->graphQlMutation($query); + } + + /** + * @param string $cartId + * @return void + */ + private function placeOrder(string $cartId): void + { + $query = <<<QUERY +mutation { + placeOrder( + input: { + cart_id: "{$cartId}" + } + ) { + order { + order_id + } + } +} +QUERY; + $response = $this->graphQlMutation($query); + self::assertArrayHasKey('placeOrder', $response); + self::assertArrayHasKey('order', $response['placeOrder']); + self::assertArrayHasKey('order_id', $response['placeOrder']['order']); + self::assertNotEmpty($response['placeOrder']['order']['order_id']); + } + + public function tearDown() + { + $this->deleteQuote(); + $this->deleteOrder(); + parent::tearDown(); + } + + /** + * @return void + */ + private function deleteQuote(): void + { + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { + $this->quoteResource->delete($quote); + + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $quoteIdMask->setQuoteId($quote->getId()) + ->delete(); + } + } + + /** + * @return void + */ + private function deleteOrder() + { + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', true); + + $orderCollection = $this->orderCollectionFactory->create(); + foreach ($orderCollection as $order) { + $this->orderRepository->delete($order); + } + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', false); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php index adb2879e186b1..ddce2cfbffbcb 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php @@ -7,9 +7,8 @@ namespace Magento\GraphQl\Quote\Guest; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -26,37 +25,26 @@ class CreateEmptyCartTest extends GraphQlAbstract private $guestCartRepository; /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var QuoteFactory + * @var QuoteCollectionFactory */ - private $quoteFactory; + private $quoteCollectionFactory; /** - * @var MaskedQuoteIdToQuoteIdInterface + * @var QuoteResource */ - private $maskedQuoteIdToQuoteId; + private $quoteResource; /** * @var QuoteIdMaskFactory */ private $quoteIdMaskFactory; - /** - * @var string - */ - private $maskedQuoteId; - protected function setUp() { $objectManager = Bootstrap::getObjectManager(); $this->guestCartRepository = $objectManager->get(GuestCartRepositoryInterface::class); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->maskedQuoteIdToQuoteId = $objectManager->get(MaskedQuoteIdToQuoteIdInterface::class); $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); } @@ -69,7 +57,6 @@ public function testCreateEmptyCart() self::assertNotEmpty($response['createEmptyCart']); $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); - $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertNull($guestCart->getCustomer()->getId()); @@ -110,15 +97,12 @@ private function getQuery(): string public function tearDown() { - if (null !== $this->maskedQuoteId) { - $quoteId = $this->maskedQuoteIdToQuoteId->execute($this->maskedQuoteId); - - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $quoteId); + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { $this->quoteResource->delete($quote); $quoteIdMask = $this->quoteIdMaskFactory->create(); - $quoteIdMask->setQuoteId($quoteId) + $quoteIdMask->setQuoteId($quote->getId()) ->delete(); } parent::tearDown(); From b82d771f40a9cfa660e8c9f577e28408168edfc2 Mon Sep 17 00:00:00 2001 From: anzin <andrii.zinkevych@smile-ukraine.com> Date: Sat, 13 Apr 2019 17:56:48 +0300 Subject: [PATCH 584/603] magento/graphql-ce#607: Expanded "createdEmptyCart" mutation with not required parameter "cart_id" --- app/code/Magento/Quote/etc/frontend/di.xml | 2 +- .../Model/Resolver/CreateEmptyCart.php | 35 ++++++++++++++++--- .../Plugin/MaskAlreadySetException.php | 33 +++++++++++++++++ .../Magento/QuoteGraphQl/etc/graphql/di.xml | 3 ++ .../Magento/QuoteGraphQl/etc/schema.graphqls | 6 +++- 5 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php diff --git a/app/code/Magento/Quote/etc/frontend/di.xml b/app/code/Magento/Quote/etc/frontend/di.xml index ecad94fbbc249..cb19d73797c4b 100644 --- a/app/code/Magento/Quote/etc/frontend/di.xml +++ b/app/code/Magento/Quote/etc/frontend/di.xml @@ -19,6 +19,6 @@ <plugin name="update_quote_store_after_switch_store_view" type="Magento\Quote\Plugin\UpdateQuoteStore"/> </type> <type name="Magento\Customer\Model\ResourceModel\Customer"> - <plugin name="cart_recollect_on_group_change" type="Magento\Quote\Plugin\RecollectOnGroupChange"/> + <plugin name="cart_recollect_on_group_change" type="Magento\Quote\Plugin\MaskAlreadySetException"/> </type> </config> diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php index 06123abe615e6..b67db1fa0dc2b 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php @@ -8,6 +8,8 @@ namespace Magento\QuoteGraphQl\Model\Resolver; use Magento\Framework\GraphQl\Config\Element\Field; +use Magento\Framework\GraphQl\Exception\GraphQlAlreadyExistsException; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Api\CartManagementInterface; @@ -64,18 +66,43 @@ public function __construct( public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { $customerId = $context->getUserId(); + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $maskedQuoteId = null; + + if (isset($args['input']['cart_id'])) { + $maskedQuoteId = $args['input']['cart_id']; + + if ($quoteIdMask->load($maskedQuoteId, 'masked_id') && $quoteIdMask->getQuoteId()) { + throw new GraphQlAlreadyExistsException(__('Specified "cart_id" already exists')); + } + + if (strlen($maskedQuoteId) > 32) { + throw new GraphQlInputException(__('Specified "cart_id" max size is 32')); + } + } if (0 !== $customerId && null !== $customerId) { $quoteId = $this->cartManagement->createEmptyCartForCustomer($customerId); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quoteId); + $existsMaskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quoteId); + + if (empty($existsMaskedQuoteId)) { + if (null !== $maskedQuoteId) { + $quoteIdMask->setMaskedId($maskedQuoteId); + } - if (empty($maskedQuoteId)) { - $quoteIdMask = $this->quoteIdMaskFactory->create(); $quoteIdMask->setQuoteId($quoteId)->save(); $maskedQuoteId = $quoteIdMask->getMaskedId(); } } else { - $maskedQuoteId = $this->guestCartManagement->createEmptyCart(); + if (null !== $maskedQuoteId) { + $cartId = $this->cartManagement->createEmptyCart(); + $quoteIdMask + ->setQuoteId($cartId) + ->setMaskedId($maskedQuoteId) + ->save(); + } else { + $maskedQuoteId = $this->guestCartManagement->createEmptyCart(); + } } return $maskedQuoteId; diff --git a/app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php b/app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php new file mode 100644 index 0000000000000..2ed364f6f4beb --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\QuoteGraphQl\Plugin; + +use Magento\Quote\Model\QuoteIdMask; + +/** + * Don't proceed beforeSave method if masked id already set. + */ +class MaskAlreadySetException +{ + /** + * @param \Magento\Quote\Model\QuoteIdMask $subject + * @param \Closure $proceed + * + * @return \Magento\Quote\Model\QuoteIdMask + */ + public function aroundBeforeSave(QuoteIdMask $subject, \Closure $proceed) + { + $maskedId = $subject->getMaskedId(); + + if (!$maskedId) { + $proceed(); + } + + return $subject; + } +} diff --git a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml index c7389cf667845..7aa6ce77bfbdf 100644 --- a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml @@ -10,4 +10,7 @@ type="Magento\QuoteGraphQl\Model\Cart\SetShippingAddressesOnCart"/> <preference for="Magento\QuoteGraphQl\Model\Cart\SetShippingMethodsOnCartInterface" type="Magento\QuoteGraphQl\Model\Cart\SetShippingMethodsOnCart"/> + <type name="Magento\Quote\Model\QuoteIdMask"> + <plugin name="mask_already_set_exception" type="Magento\QuoteGraphQl\Plugin\MaskAlreadySetException"/> + </type> </config> diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 711e6cbc7f5f6..a9784e97c8952 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -6,7 +6,7 @@ type Query { } type Mutation { - createEmptyCart: String @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CreateEmptyCart") @doc(description:"Creates an empty shopping cart for a guest or logged in user") + createEmptyCart(input: createEmptyCartInput): String @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CreateEmptyCart") @doc(description:"Creates an empty shopping cart for a guest or logged in user") addSimpleProductsToCart(input: AddSimpleProductsToCartInput): AddSimpleProductsToCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AddSimpleProductsToCart") addVirtualProductsToCart(input: AddVirtualProductsToCartInput): AddVirtualProductsToCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AddSimpleProductsToCart") applyCouponToCart(input: ApplyCouponToCartInput): ApplyCouponToCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ApplyCouponToCart") @@ -21,6 +21,10 @@ type Mutation { placeOrder(input: PlaceOrderInput): PlaceOrderOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\PlaceOrder") } +input createEmptyCartInput { + cart_id: String +} + input AddSimpleProductsToCartInput { cart_id: String! cartItems: [SimpleProductCartItemInput!]! From 38f473c565baab39e4b2c81ee79f5ab8b9224aca Mon Sep 17 00:00:00 2001 From: anzin <andrii.zinkevych@smile-ukraine.com> Date: Sat, 13 Apr 2019 18:10:17 +0300 Subject: [PATCH 585/603] magento/graphql-ce#607: Fixed own mistake --- app/code/Magento/Quote/etc/frontend/di.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Quote/etc/frontend/di.xml b/app/code/Magento/Quote/etc/frontend/di.xml index cb19d73797c4b..ecad94fbbc249 100644 --- a/app/code/Magento/Quote/etc/frontend/di.xml +++ b/app/code/Magento/Quote/etc/frontend/di.xml @@ -19,6 +19,6 @@ <plugin name="update_quote_store_after_switch_store_view" type="Magento\Quote\Plugin\UpdateQuoteStore"/> </type> <type name="Magento\Customer\Model\ResourceModel\Customer"> - <plugin name="cart_recollect_on_group_change" type="Magento\Quote\Plugin\MaskAlreadySetException"/> + <plugin name="cart_recollect_on_group_change" type="Magento\Quote\Plugin\RecollectOnGroupChange"/> </type> </config> From 9009ccc8c3011324dccc9d168b30e3bfd11cd948 Mon Sep 17 00:00:00 2001 From: Harniuk Bohdan <bohar@smile.fr> Date: Tue, 16 Apr 2019 13:42:16 +0300 Subject: [PATCH 586/603] GraphQl-607: Expand createEmptyCart mutation --- .../Model/Resolver/CreateEmptyCart.php | 6 +- .../Quote/Customer/CreateEmptyCartTest.php | 105 ++++++++++++++++++ 2 files changed, 108 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php index b67db1fa0dc2b..ba5e1dea42727 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php @@ -73,11 +73,11 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $maskedQuoteId = $args['input']['cart_id']; if ($quoteIdMask->load($maskedQuoteId, 'masked_id') && $quoteIdMask->getQuoteId()) { - throw new GraphQlAlreadyExistsException(__('Specified "cart_id" already exists')); + throw new GraphQlAlreadyExistsException(__('Specified parameter "cart_id" is non unique.')); } - if (strlen($maskedQuoteId) > 32) { - throw new GraphQlInputException(__('Specified "cart_id" max size is 32')); + if (mb_strlen($maskedQuoteId) > 32) { + throw new GraphQlInputException(__('"cart_id" length have to be less than or equal to 32.')); } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php index fc66e4647e576..575edbd1885f1 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php @@ -15,6 +15,10 @@ use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; use Magento\Quote\Api\GuestCartRepositoryInterface; +use Magento\Framework\Math\Random as RandomDataGenerator; +use Magento\Framework\Exception\AuthenticationException; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Exception\LocalizedException; /** * Test for empty cart creation mutation for customer @@ -56,6 +60,11 @@ class CreateEmptyCartTest extends GraphQlAbstract */ private $maskedQuoteId; + /** + * @var RandomDataGenerator + */ + private $randomDataGenerator; + protected function setUp() { $objectManager = Bootstrap::getObjectManager(); @@ -65,10 +74,14 @@ protected function setUp() $this->quoteFactory = $objectManager->get(QuoteFactory::class); $this->maskedQuoteIdToQuoteId = $objectManager->get(MaskedQuoteIdToQuoteIdInterface::class); $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); + $this->randomDataGenerator = $objectManager->get(RandomDataGenerator::class); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php + * + * @throws AuthenticationException + * @throws NoSuchEntityException */ public function testCreateEmptyCart() { @@ -86,6 +99,29 @@ public function testCreateEmptyCart() self::assertEquals('default', $guestCart->getStore()->getCode()); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * + * @throws LocalizedException + * @throws NoSuchEntityException + */ + public function testCreateEmptyCartWithCartId() + { + $uniqueHash = $this->randomDataGenerator->getUniqueHash(); + + $query = $this->getQueryWithCartId('cart_id : "' . $uniqueHash . '"'); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); + + self::assertArrayHasKey('createEmptyCart', $response); + self::assertNotEmpty($response['createEmptyCart']); + + $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); + $this->maskedQuoteId = $response['createEmptyCart']; + + self::assertNotNull($guestCart->getId()); + self::assertEquals(1, $guestCart->getCustomer()->getId()); + } + /** * @magentoApiDataFixture Magento/Store/_files/second_store.php * @magentoApiDataFixture Magento/Customer/_files/customer.php @@ -110,6 +146,24 @@ public function testCreateEmptyCartWithNotDefaultStore() self::assertEquals('fixture_second_store', $guestCart->getStore()->getCode()); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @dataProvider dataProviderValidateCreateEmptyCartWithSpecifiedCartId + * @param string $input + * @param string $message + * @throws \Exception + */ + public function testValidateCreateEmptyCartWithSpecifiedCartId(string $input, string $message) + { + $input = str_replace('provide_non_unique_id', $this->addEmptyCartWithCartId(), $input); + $input = str_replace('provide_hash_with_prefix', $this->randomDataGenerator->getUniqueHash('prefix'), $input); + + $query = $this->getQueryWithCartId($input); + + $this->expectExceptionMessage($message); + $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); + } + /** * @return string */ @@ -122,10 +176,28 @@ private function getQuery(): string QUERY; } + /** + * @param string $input + * @return string + */ + private function getQueryWithCartId(string $input): string + { + return <<<QUERY +mutation { + createEmptyCart( + input : { + {$input} + } + ) +} +QUERY; + } + /** * @param string $username * @param string $password * @return array + * @throws AuthenticationException */ private function getHeaderMapWithCustomerToken( string $username = 'customer@example.com', @@ -151,4 +223,37 @@ public function tearDown() } parent::tearDown(); } + + /** + * Return masked id for created empty cart. + * + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @return mixed + * @throws LocalizedException + */ + private function addEmptyCartWithCartId() + { + $uniqueHash = $this->randomDataGenerator->getUniqueHash(); + $query = $this->getQueryWithCartId('cart_id : "' . $uniqueHash . '"'); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); + + return $response['createEmptyCart']; + } + + /** + * @return array + */ + public function dataProviderValidateCreateEmptyCartWithSpecifiedCartId(): array + { + return [ + 'cart_id_unique_checking' => [ + 'cart_id: "provide_non_unique_id"', + 'Specified parameter "cart_id" is non unique.' + ], + 'cart_id_length_checking' => [ + 'cart_id: "provide_hash_with_prefix"', + '"cart_id" length have to be less than or equal to 32.' + ], + ]; + } } From e80423cd565a3f1194261059a4620bfa18450019 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 19 Apr 2019 14:27:35 -0500 Subject: [PATCH 587/603] Minor fixes for magento/magento-functional-tests-migration#323: Convert AccessAdminWithStoreCodeInUrlTest to MFTF --- ...ml => AssertAdminDashboardPageIsVisibleActionGroup.xml} | 2 +- .../Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml | 3 ++- ...p.xml => AssertStorefrontStoreCodeInUrlActionGroup.xml} | 7 +++++-- .../Test/Mftf/Data/StoreConfigData.xml} | 0 .../Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml | 3 ++- .../ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml | 6 +++--- 6 files changed, 13 insertions(+), 8 deletions(-) rename app/code/Magento/Backend/Test/Mftf/ActionGroup/{AdminAssertDashboardPageIsVisibleActionGroup.xml => AssertAdminDashboardPageIsVisibleActionGroup.xml} (89%) rename app/code/Magento/Store/Test/Mftf/ActionGroup/{StorefrontAssertStoreCodeInUrlActionGroup.xml => AssertStorefrontStoreCodeInUrlActionGroup.xml} (53%) rename app/code/Magento/{Backend/Test/Mftf/Data/BackendConfigData.xml => Store/Test/Mftf/Data/StoreConfigData.xml} (100%) diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminAssertDashboardPageIsVisibleActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminDashboardPageIsVisibleActionGroup.xml similarity index 89% rename from app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminAssertDashboardPageIsVisibleActionGroup.xml rename to app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminDashboardPageIsVisibleActionGroup.xml index df22bb27d6b88..1c86a736ac2f1 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminAssertDashboardPageIsVisibleActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminDashboardPageIsVisibleActionGroup.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="AdminAssertDashboardPageIsVisibleActionGroup"> + <actionGroup name="AssertAdminDashboardPageIsVisibleActionGroup"> <seeInCurrentUrl url="{{AdminDashboardPage.url}}" stepKey="seeDashboardUrl"/> <see userInput="Dashboard" selector="{{AdminHeaderSection.pageTitle}}" stepKey="seeDashboardTitle"/> </actionGroup> diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml index 51ba1a142803d..5485dcaea33ee 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminUserLoginWithStoreCodeInUrlTest.xml @@ -13,6 +13,7 @@ <features value="Backend"/> <title value="Admin panel should be accessible with Add Store Code to URL setting enabled"/> <description value="Admin panel should be accessible with Add Store Code to URL setting enabled"/> + <testCaseId value="MC-14279" /> <group value="backend"/> <group value="mtf_migrated"/> </annotations> @@ -24,6 +25,6 @@ </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <actionGroup ref="AdminAssertDashboardPageIsVisibleActionGroup" stepKey="seeDashboardPage"/> + <actionGroup ref="AssertAdminDashboardPageIsVisibleActionGroup" stepKey="seeDashboardPage"/> </test> </tests> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontAssertStoreCodeInUrlActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreCodeInUrlActionGroup.xml similarity index 53% rename from app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontAssertStoreCodeInUrlActionGroup.xml rename to app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreCodeInUrlActionGroup.xml index 974526afbf21c..3daa1c25a1737 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontAssertStoreCodeInUrlActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AssertStorefrontStoreCodeInUrlActionGroup.xml @@ -7,7 +7,10 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="StorefrontAssertStoreCodeInUrlActionGroup"> - <seeInCurrentUrl url="{{StorefrontHomePage.url}}{{_defaultStore.code}}" stepKey="seeStoreCodeInURL"/> + <actionGroup name="AssertStorefrontStoreCodeInUrlActionGroup"> + <arguments> + <argument name="storeCode" type="string" defaultValue="{{_defaultStore.code}}" /> + </arguments> + <seeInCurrentUrl url="{{StorefrontHomePage.url}}{{storeCode}}" stepKey="seeStoreCodeInURL"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Data/BackendConfigData.xml b/app/code/Magento/Store/Test/Mftf/Data/StoreConfigData.xml similarity index 100% rename from app/code/Magento/Backend/Test/Mftf/Data/BackendConfigData.xml rename to app/code/Magento/Store/Test/Mftf/Data/StoreConfigData.xml diff --git a/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml b/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml index 7bee46da1a226..95f5a9cd2d669 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml @@ -13,6 +13,7 @@ <features value="Backend"/> <title value="Store code should be added to storefront URL if the corresponding configuration is enabled"/> <description value="Store code should be added to storefront URL if the corresponding configuration is enabled"/> + <testCaseId value="MC-15944" /> <group value="store"/> <group value="mtf_migrated"/> </annotations> @@ -24,6 +25,6 @@ </after> <actionGroup ref="StorefrontClickOnHeaderLogoActionGroup" stepKey="clickOnStorefrontHeaderLogo"/> - <actionGroup ref="StorefrontAssertStoreCodeInUrlActionGroup" stepKey="seeStoreCodeInUrl"/> + <actionGroup ref="AssertStorefrontStoreCodeInUrlActionGroup" stepKey="seeStoreCodeInUrl"/> </test> </tests> diff --git a/app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml b/app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml index 6e45429b9e1e8..cd4117a4cfa6e 100644 --- a/app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml +++ b/app/code/Magento/Theme/Test/Mftf/ActionGroup/StorefrontClickOnHeaderLogoActionGroup.xml @@ -8,9 +8,9 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="StorefrontClickOnHeaderLogoActionGroup"> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="gotToHomePage"/> - <waitForPageLoad stepKey="waitForHomePageLoaded1"/> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToHomePage"/> + <waitForPageLoad stepKey="waitForHomePageLoaded"/> <click selector="{{StorefrontHeaderSection.logoLink}}" stepKey="clickOnLogo"/> - <waitForPageLoad stepKey="waitForHomePageLoaded2"/> + <waitForPageLoad stepKey="waitForHomePageLoadedAfterClickOnLogo"/> </actionGroup> </actionGroups> From a6cb82926e832e47890cac166497d646da852682 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Fri, 19 Apr 2019 15:27:30 -0500 Subject: [PATCH 588/603] GraphQL-607: Expand `createEmptyCart` mutation --- app/code/Magento/Quote/Model/QuoteIdMask.php | 5 +- .../Model/Cart/CreateEmptyCartForCustomer.php | 67 ++++++++ .../Model/Cart/CreateEmptyCartForGuest.php | 66 +++++++ .../Model/Resolver/CreateEmptyCart.php | 111 ++++++------ .../Plugin/MaskAlreadySetException.php | 33 ---- .../Magento/QuoteGraphQl/etc/graphql/di.xml | 3 - .../Quote/Customer/CreateEmptyCartTest.php | 161 ++++++------------ .../Quote/Guest/CreateEmptyCartTest.php | 93 +++++++--- 8 files changed, 306 insertions(+), 233 deletions(-) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php delete mode 100644 app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php diff --git a/app/code/Magento/Quote/Model/QuoteIdMask.php b/app/code/Magento/Quote/Model/QuoteIdMask.php index 7950ab47c3665..47b02db7650df 100644 --- a/app/code/Magento/Quote/Model/QuoteIdMask.php +++ b/app/code/Magento/Quote/Model/QuoteIdMask.php @@ -53,11 +53,14 @@ protected function _construct() * Initialize quote identifier before save * * @return $this + * @throws \Magento\Framework\Exception\LocalizedException */ public function beforeSave() { parent::beforeSave(); - $this->setMaskedId($this->randomDataGenerator->getUniqueHash()); + if (empty($this->getMaskedId())) { + $this->setMaskedId($this->randomDataGenerator->getUniqueHash()); + } return $this; } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php new file mode 100644 index 0000000000000..142542e7b6aa5 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\QuoteGraphQl\Model\Cart; + +use Magento\Quote\Api\CartManagementInterface; +use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote\QuoteIdMask as QuoteIdMaskResourceModel; + +/** + * Create empty cart for customer + */ +class CreateEmptyCartForCustomer +{ + /** + * @var CartManagementInterface + */ + private $cartManagement; + + /** + * @var QuoteIdMaskFactory + */ + private $quoteIdMaskFactory; + + /** + * @var QuoteIdMaskResourceModel + */ + private $quoteIdMaskResourceModel; + + /** + * @param CartManagementInterface $cartManagement + * @param QuoteIdMaskFactory $quoteIdMaskFactory + * @param QuoteIdMaskResourceModel $quoteIdMaskResourceModel + */ + public function __construct( + CartManagementInterface $cartManagement, + QuoteIdMaskFactory $quoteIdMaskFactory, + QuoteIdMaskResourceModel $quoteIdMaskResourceModel + ) { + $this->cartManagement = $cartManagement; + $this->quoteIdMaskFactory = $quoteIdMaskFactory; + $this->quoteIdMaskResourceModel = $quoteIdMaskResourceModel; + } + + /** + * @param string|null $predefinedMaskedQuoteId + * @return string + */ + public function execute(int $customerId, string $predefinedMaskedQuoteId = null): string + { + $quoteId = $this->cartManagement->createEmptyCartForCustomer($customerId); + + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $quoteIdMask->setQuoteId($quoteId); + + if (isset($predefinedMaskedQuoteId)) { + $quoteIdMask->setMaskedId($predefinedMaskedQuoteId); + } + + $this->quoteIdMaskResourceModel->save($quoteIdMask); + return $quoteIdMask->getMaskedId(); + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php new file mode 100644 index 0000000000000..99eef31e64a47 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\QuoteGraphQl\Model\Cart; + +use Magento\Quote\Api\GuestCartManagementInterface; +use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote\QuoteIdMask as QuoteIdMaskResourceModel; + +/** + * Create empty cart for guest + */ +class CreateEmptyCartForGuest +{ + /** + * @var GuestCartManagementInterface + */ + private $guestCartManagement; + + /** + * @var QuoteIdMaskFactory + */ + private $quoteIdMaskFactory; + + /** + * @var QuoteIdMaskResourceModel + */ + private $quoteIdMaskResourceModel; + + /** + * @param GuestCartManagementInterface $guestCartManagement + * @param QuoteIdMaskFactory $quoteIdMaskFactory + * @param QuoteIdMaskResourceModel $quoteIdMaskResourceModel + */ + public function __construct( + GuestCartManagementInterface $guestCartManagement, + QuoteIdMaskFactory $quoteIdMaskFactory, + QuoteIdMaskResourceModel $quoteIdMaskResourceModel + ) { + $this->guestCartManagement = $guestCartManagement; + $this->quoteIdMaskFactory = $quoteIdMaskFactory; + $this->quoteIdMaskResourceModel = $quoteIdMaskResourceModel; + } + + /** + * @param string|null $predefinedMaskedQuoteId + * @return string + */ + public function execute(string $predefinedMaskedQuoteId = null): string + { + $maskedQuoteId = $this->guestCartManagement->createEmptyCart(); + + if (isset($predefinedMaskedQuoteId)) { + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $this->quoteIdMaskResourceModel->load($quoteIdMask, $maskedQuoteId, 'masked_id'); + + $quoteIdMask->setMaskedId($predefinedMaskedQuoteId); + $this->quoteIdMaskResourceModel->save($quoteIdMask); + } + return $predefinedMaskedQuoteId ?? $maskedQuoteId; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php index ba5e1dea42727..9a559eda6ee64 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php @@ -7,15 +7,15 @@ namespace Magento\QuoteGraphQl\Model\Resolver; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Exception\GraphQlAlreadyExistsException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; -use Magento\Quote\Api\CartManagementInterface; -use Magento\Quote\Api\GuestCartManagementInterface; -use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; -use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; +use Magento\QuoteGraphQl\Model\Cart\CreateEmptyCartForCustomer; +use Magento\QuoteGraphQl\Model\Cart\CreateEmptyCartForGuest; /** * @inheritdoc @@ -23,41 +23,33 @@ class CreateEmptyCart implements ResolverInterface { /** - * @var CartManagementInterface + * @var CreateEmptyCartForCustomer */ - private $cartManagement; + private $createEmptyCartForCustomer; /** - * @var GuestCartManagementInterface + * @var CreateEmptyCartForGuest */ - private $guestCartManagement; + private $createEmptyCartForGuest; /** - * @var QuoteIdToMaskedQuoteIdInterface + * @var MaskedQuoteIdToQuoteIdInterface */ - private $quoteIdToMaskedId; + private $maskedQuoteIdToQuoteId; /** - * @var QuoteIdMaskFactory - */ - private $quoteIdMaskFactory; - - /** - * @param CartManagementInterface $cartManagement - * @param GuestCartManagementInterface $guestCartManagement - * @param QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedId - * @param QuoteIdMaskFactory $quoteIdMaskFactory + * @param CreateEmptyCartForCustomer $createEmptyCartForCustomer + * @param CreateEmptyCartForGuest $createEmptyCartForGuest + * @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId */ public function __construct( - CartManagementInterface $cartManagement, - GuestCartManagementInterface $guestCartManagement, - QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedId, - QuoteIdMaskFactory $quoteIdMaskFactory + CreateEmptyCartForCustomer $createEmptyCartForCustomer, + CreateEmptyCartForGuest $createEmptyCartForGuest, + MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId ) { - $this->cartManagement = $cartManagement; - $this->guestCartManagement = $guestCartManagement; - $this->quoteIdToMaskedId = $quoteIdToMaskedId; - $this->quoteIdMaskFactory = $quoteIdMaskFactory; + $this->createEmptyCartForCustomer = $createEmptyCartForCustomer; + $this->createEmptyCartForGuest = $createEmptyCartForGuest; + $this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId; } /** @@ -66,45 +58,46 @@ public function __construct( public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { $customerId = $context->getUserId(); - $quoteIdMask = $this->quoteIdMaskFactory->create(); - $maskedQuoteId = null; + $predefinedMaskedQuoteId = null; if (isset($args['input']['cart_id'])) { - $maskedQuoteId = $args['input']['cart_id']; - - if ($quoteIdMask->load($maskedQuoteId, 'masked_id') && $quoteIdMask->getQuoteId()) { - throw new GraphQlAlreadyExistsException(__('Specified parameter "cart_id" is non unique.')); - } - - if (mb_strlen($maskedQuoteId) > 32) { - throw new GraphQlInputException(__('"cart_id" length have to be less than or equal to 32.')); - } + $predefinedMaskedQuoteId = $args['input']['cart_id']; + $this->validateMaskedId($predefinedMaskedQuoteId); } - if (0 !== $customerId && null !== $customerId) { - $quoteId = $this->cartManagement->createEmptyCartForCustomer($customerId); - $existsMaskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quoteId); + $maskedQuoteId = (0 === $customerId || null === $customerId) + ? $this->createEmptyCartForGuest->execute($predefinedMaskedQuoteId) + : $this->createEmptyCartForCustomer->execute($customerId, $predefinedMaskedQuoteId); + return $maskedQuoteId; + } - if (empty($existsMaskedQuoteId)) { - if (null !== $maskedQuoteId) { - $quoteIdMask->setMaskedId($maskedQuoteId); - } + /** + * @param string $maskedId + * @throws GraphQlAlreadyExistsException + * @throws GraphQlInputException + */ + private function validateMaskedId(string $maskedId): void + { + if (mb_strlen($maskedId) != 32) { + throw new GraphQlInputException(__('Cart ID length should to be 32 symbols.')); + } - $quoteIdMask->setQuoteId($quoteId)->save(); - $maskedQuoteId = $quoteIdMask->getMaskedId(); - } - } else { - if (null !== $maskedQuoteId) { - $cartId = $this->cartManagement->createEmptyCart(); - $quoteIdMask - ->setQuoteId($cartId) - ->setMaskedId($maskedQuoteId) - ->save(); - } else { - $maskedQuoteId = $this->guestCartManagement->createEmptyCart(); - } + if ($this->isQuoteWithSuchMaskedIdAlreadyExists($maskedId)) { + throw new GraphQlAlreadyExistsException(__('Cart with ID "%1" already exists.', $maskedId)); } + } - return $maskedQuoteId; + /** + * @param string $maskedId + * @return bool + */ + private function isQuoteWithSuchMaskedIdAlreadyExists(string $maskedId): bool + { + try { + $this->maskedQuoteIdToQuoteId->execute($maskedId); + return true; + } catch (NoSuchEntityException $e) { + return false; + } } } diff --git a/app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php b/app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php deleted file mode 100644 index 2ed364f6f4beb..0000000000000 --- a/app/code/Magento/QuoteGraphQl/Plugin/MaskAlreadySetException.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\QuoteGraphQl\Plugin; - -use Magento\Quote\Model\QuoteIdMask; - -/** - * Don't proceed beforeSave method if masked id already set. - */ -class MaskAlreadySetException -{ - /** - * @param \Magento\Quote\Model\QuoteIdMask $subject - * @param \Closure $proceed - * - * @return \Magento\Quote\Model\QuoteIdMask - */ - public function aroundBeforeSave(QuoteIdMask $subject, \Closure $proceed) - { - $maskedId = $subject->getMaskedId(); - - if (!$maskedId) { - $proceed(); - } - - return $subject; - } -} diff --git a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml index 7aa6ce77bfbdf..c7389cf667845 100644 --- a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml @@ -10,7 +10,4 @@ type="Magento\QuoteGraphQl\Model\Cart\SetShippingAddressesOnCart"/> <preference for="Magento\QuoteGraphQl\Model\Cart\SetShippingMethodsOnCartInterface" type="Magento\QuoteGraphQl\Model\Cart\SetShippingMethodsOnCart"/> - <type name="Magento\Quote\Model\QuoteIdMask"> - <plugin name="mask_already_set_exception" type="Magento\QuoteGraphQl\Plugin\MaskAlreadySetException"/> - </type> </config> diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php index 575edbd1885f1..fbd0cf19740d7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php @@ -8,17 +8,12 @@ namespace Magento\GraphQl\Quote\Customer; use Magento\Integration\Api\CustomerTokenServiceInterface; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; use Magento\Quote\Api\GuestCartRepositoryInterface; -use Magento\Framework\Math\Random as RandomDataGenerator; -use Magento\Framework\Exception\AuthenticationException; -use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Framework\Exception\LocalizedException; /** * Test for empty cart creation mutation for customer @@ -36,52 +31,32 @@ class CreateEmptyCartTest extends GraphQlAbstract private $customerTokenService; /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var QuoteFactory + * @var QuoteCollectionFactory */ - private $quoteFactory; + private $quoteCollectionFactory; /** - * @var MaskedQuoteIdToQuoteIdInterface + * @var QuoteResource */ - private $maskedQuoteIdToQuoteId; + private $quoteResource; /** * @var QuoteIdMaskFactory */ private $quoteIdMaskFactory; - /** - * @var string - */ - private $maskedQuoteId; - - /** - * @var RandomDataGenerator - */ - private $randomDataGenerator; - protected function setUp() { $objectManager = Bootstrap::getObjectManager(); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); $this->guestCartRepository = $objectManager->get(GuestCartRepositoryInterface::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->maskedQuoteIdToQuoteId = $objectManager->get(MaskedQuoteIdToQuoteIdInterface::class); $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); - $this->randomDataGenerator = $objectManager->get(RandomDataGenerator::class); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * - * @throws AuthenticationException - * @throws NoSuchEntityException */ public function testCreateEmptyCart() { @@ -92,7 +67,6 @@ public function testCreateEmptyCart() self::assertNotEmpty($response['createEmptyCart']); $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); - $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertEquals(1, $guestCart->getCustomer()->getId()); @@ -100,95 +74,95 @@ public function testCreateEmptyCart() } /** + * @magentoApiDataFixture Magento/Store/_files/second_store.php * @magentoApiDataFixture Magento/Customer/_files/customer.php - * - * @throws LocalizedException - * @throws NoSuchEntityException */ - public function testCreateEmptyCartWithCartId() + public function testCreateEmptyCartWithNotDefaultStore() { - $uniqueHash = $this->randomDataGenerator->getUniqueHash(); + $query = $this->getQuery(); - $query = $this->getQueryWithCartId('cart_id : "' . $uniqueHash . '"'); - $response = $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); + $headerMap = $this->getHeaderMapWithCustomerToken(); + $headerMap['Store'] = 'fixture_second_store'; + $response = $this->graphQlMutation($query, [], '', $headerMap); self::assertArrayHasKey('createEmptyCart', $response); self::assertNotEmpty($response['createEmptyCart']); + /* guestCartRepository is used for registered customer to get the cart hash */ $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); - $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertEquals(1, $guestCart->getCustomer()->getId()); + self::assertEquals('fixture_second_store', $guestCart->getStore()->getCode()); } /** - * @magentoApiDataFixture Magento/Store/_files/second_store.php * @magentoApiDataFixture Magento/Customer/_files/customer.php */ - public function testCreateEmptyCartWithNotDefaultStore() + public function testCreateEmptyCartWithPredefinedCartId() { - $query = $this->getQuery(); + $predefinedCartId = '572cda51902b5b517c0e1a2b2fd004b4'; - $headerMap = $this->getHeaderMapWithCustomerToken(); - $headerMap['Store'] = 'fixture_second_store'; - $response = $this->graphQlMutation($query, [], '', $headerMap); + $query = <<<QUERY +mutation { + createEmptyCart (input: {cart_id: "{$predefinedCartId}"}) +} +QUERY; + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); self::assertArrayHasKey('createEmptyCart', $response); - self::assertNotEmpty($response['createEmptyCart']); + self::assertEquals($predefinedCartId, $response['createEmptyCart']); - /* guestCartRepository is used for registered customer to get the cart hash */ $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); - $this->maskedQuoteId = $response['createEmptyCart']; - self::assertNotNull($guestCart->getId()); self::assertEquals(1, $guestCart->getCustomer()->getId()); - self::assertEquals('fixture_second_store', $guestCart->getStore()->getCode()); } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @dataProvider dataProviderValidateCreateEmptyCartWithSpecifiedCartId - * @param string $input - * @param string $message - * @throws \Exception + * + * @expectedException \Exception + * @expectedExceptionMessage Cart with ID "572cda51902b5b517c0e1a2b2fd004b4" already exists. */ - public function testValidateCreateEmptyCartWithSpecifiedCartId(string $input, string $message) + public function testCreateEmptyCartIfPredefinedCartIdAlreadyExists() { - $input = str_replace('provide_non_unique_id', $this->addEmptyCartWithCartId(), $input); - $input = str_replace('provide_hash_with_prefix', $this->randomDataGenerator->getUniqueHash('prefix'), $input); - - $query = $this->getQueryWithCartId($input); + $predefinedCartId = '572cda51902b5b517c0e1a2b2fd004b4'; - $this->expectExceptionMessage($message); + $query = <<<QUERY +mutation { + createEmptyCart (input: {cart_id: "{$predefinedCartId}"}) +} +QUERY; + $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); } /** - * @return string + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * + * @expectedException \Exception + * @expectedExceptionMessage Cart ID length should to be 32 symbols. */ - private function getQuery(): string + public function testCreateEmptyCartWithWrongPredefinedCartId() { - return <<<QUERY + $predefinedCartId = '572'; + + $query = <<<QUERY mutation { - createEmptyCart + createEmptyCart (input: {cart_id: "{$predefinedCartId}"}) } QUERY; + $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); } /** - * @param string $input * @return string */ - private function getQueryWithCartId(string $input): string + private function getQuery(): string { return <<<QUERY mutation { - createEmptyCart( - input : { - {$input} - } - ) + createEmptyCart } QUERY; } @@ -197,7 +171,6 @@ private function getQueryWithCartId(string $input): string * @param string $username * @param string $password * @return array - * @throws AuthenticationException */ private function getHeaderMapWithCustomerToken( string $username = 'customer@example.com', @@ -210,50 +183,14 @@ private function getHeaderMapWithCustomerToken( public function tearDown() { - if (null !== $this->maskedQuoteId) { - $quoteId = $this->maskedQuoteIdToQuoteId->execute($this->maskedQuoteId); - - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $quoteId); + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { $this->quoteResource->delete($quote); $quoteIdMask = $this->quoteIdMaskFactory->create(); - $quoteIdMask->setQuoteId($quoteId) + $quoteIdMask->setQuoteId($quote->getId()) ->delete(); } parent::tearDown(); } - - /** - * Return masked id for created empty cart. - * - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @return mixed - * @throws LocalizedException - */ - private function addEmptyCartWithCartId() - { - $uniqueHash = $this->randomDataGenerator->getUniqueHash(); - $query = $this->getQueryWithCartId('cart_id : "' . $uniqueHash . '"'); - $response = $this->graphQlMutation($query, [], '', $this->getHeaderMapWithCustomerToken()); - - return $response['createEmptyCart']; - } - - /** - * @return array - */ - public function dataProviderValidateCreateEmptyCartWithSpecifiedCartId(): array - { - return [ - 'cart_id_unique_checking' => [ - 'cart_id: "provide_non_unique_id"', - 'Specified parameter "cart_id" is non unique.' - ], - 'cart_id_length_checking' => [ - 'cart_id: "provide_hash_with_prefix"', - '"cart_id" length have to be less than or equal to 32.' - ], - ]; - } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php index adb2879e186b1..6ed91d21f0ae2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php @@ -7,9 +7,8 @@ namespace Magento\GraphQl\Quote\Guest; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -26,37 +25,26 @@ class CreateEmptyCartTest extends GraphQlAbstract private $guestCartRepository; /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var QuoteFactory + * @var QuoteCollectionFactory */ - private $quoteFactory; + private $quoteCollectionFactory; /** - * @var MaskedQuoteIdToQuoteIdInterface + * @var QuoteResource */ - private $maskedQuoteIdToQuoteId; + private $quoteResource; /** * @var QuoteIdMaskFactory */ private $quoteIdMaskFactory; - /** - * @var string - */ - private $maskedQuoteId; - protected function setUp() { $objectManager = Bootstrap::getObjectManager(); $this->guestCartRepository = $objectManager->get(GuestCartRepositoryInterface::class); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->maskedQuoteIdToQuoteId = $objectManager->get(MaskedQuoteIdToQuoteIdInterface::class); $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); } @@ -69,7 +57,6 @@ public function testCreateEmptyCart() self::assertNotEmpty($response['createEmptyCart']); $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); - $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertNull($guestCart->getCustomer()->getId()); @@ -96,6 +83,65 @@ public function testCreateEmptyCartWithNotDefaultStore() self::assertSame('fixture_second_store', $guestCart->getStore()->getCode()); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + */ + public function testCreateEmptyCartWithPredefinedCartId() + { + $predefinedCartId = '572cda51902b5b517c0e1a2b2fd004b4'; + + $query = <<<QUERY +mutation { + createEmptyCart (input: {cart_id: "{$predefinedCartId}"}) +} +QUERY; + $response = $this->graphQlMutation($query); + + self::assertArrayHasKey('createEmptyCart', $response); + self::assertEquals($predefinedCartId, $response['createEmptyCart']); + + $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); + self::assertNotNull($guestCart->getId()); + self::assertNull($guestCart->getCustomer()->getId()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * + * @expectedException \Exception + * @expectedExceptionMessage Cart with ID "572cda51902b5b517c0e1a2b2fd004b4" already exists. + */ + public function testCreateEmptyCartIfPredefinedCartIdAlreadyExists() + { + $predefinedCartId = '572cda51902b5b517c0e1a2b2fd004b4'; + + $query = <<<QUERY +mutation { + createEmptyCart (input: {cart_id: "{$predefinedCartId}"}) +} +QUERY; + $this->graphQlMutation($query); + $this->graphQlMutation($query); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * + * @expectedException \Exception + * @expectedExceptionMessage Cart ID length should to be 32 symbols. + */ + public function testCreateEmptyCartWithWrongPredefinedCartId() + { + $predefinedCartId = '572'; + + $query = <<<QUERY +mutation { + createEmptyCart (input: {cart_id: "{$predefinedCartId}"}) +} +QUERY; + $this->graphQlMutation($query); + } + /** * @return string */ @@ -110,15 +156,12 @@ private function getQuery(): string public function tearDown() { - if (null !== $this->maskedQuoteId) { - $quoteId = $this->maskedQuoteIdToQuoteId->execute($this->maskedQuoteId); - - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $quoteId); + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { $this->quoteResource->delete($quote); $quoteIdMask = $this->quoteIdMaskFactory->create(); - $quoteIdMask->setQuoteId($quoteId) + $quoteIdMask->setQuoteId($quote->getId()) ->delete(); } parent::tearDown(); From eaafea1d9edf324170ac2f74eba9d82679eb5457 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Sun, 21 Apr 2019 16:01:33 -0500 Subject: [PATCH 589/603] Minor fixes for magento/magento-functional-tests-migration#581: Convert DeleteCustomerGroupEntityTest to MFTF --- ...AdminOpenNewProductFormPageActionGroup.xml | 19 ++++ .../Test/Mftf/Data/AttributeSetData.xml | 16 ++++ ...AdminProductFormAdvancedPricingSection.xml | 1 + ...NewCatalogPriceRuleFormPageActionGroup.xml | 14 +++ ...upNotOnCatalogPriceRuleFormActionGroup.xml | 20 +++++ .../Test/Mftf/Page/CatalogRuleNewPage.xml | 14 +++ .../Mftf/Test/DeleteCustomerGroupTest.xml | 17 ++++ .../AdminOpenCustomerEditPageActionGroup.xml | 17 ++++ ...ssertCustomerGroupNotInGridActionGroup.xml | 20 +++++ ...stomerGroupNotOnProductFormActionGroup.xml | 23 +++++ ...CustomerGroupOnCustomerFormActionGroup.xml | 18 ++++ .../Customer/Test/Mftf/Data/CustomerData.xml | 13 +++ .../Mftf/Test/DeleteCustomerGroupTest.xml | 89 +++++-------------- ...penNewCartPriceRuleFormPageActionGroup.xml | 14 +++ ...GroupNotOnCartPriceRuleFormActionGroup.xml | 20 +++++ .../AdminCartPriceRulesFormSection.xml | 1 + .../Mftf/Test/DeleteCustomerGroupTest.xml | 17 ++++ .../DeleteCustomerGroupEntityTest.xml | 1 + 18 files changed, 267 insertions(+), 67 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenNewProductFormPageActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Data/AttributeSetData.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminOpenNewCatalogPriceRuleFormPageActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCatalogPriceRuleFormActionGroup.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/Page/CatalogRuleNewPage.xml create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminOpenCustomerEditPageActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotInGridActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnProductFormActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupOnCustomerFormActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminOpenNewCartPriceRuleFormPageActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCartPriceRuleFormActionGroup.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenNewProductFormPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenNewProductFormPageActionGroup.xml new file mode 100644 index 0000000000000..fe859fab52667 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenNewProductFormPageActionGroup.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="AdminOpenNewProductFormPageActionGroup"> + <arguments> + <argument name="productType" type="string" defaultValue="simple" /> + <argument name="attributeSetId" type="string" defaultValue="{{defaultAttributeSet.attribute_set_id}}" /> + </arguments> + + <amOnPage url="{{AdminProductCreatePage.url(attributeSetId, productType)}}" stepKey="openProductNewPage" /> + <waitForPageLoad stepKey="waitForPageLoad" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/AttributeSetData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/AttributeSetData.xml new file mode 100644 index 0000000000000..6e1b25fb9cdc4 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Data/AttributeSetData.xml @@ -0,0 +1,16 @@ +<?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="defaultAttributeSet"> + <data key="attribute_set_id">4</data> + <data key="attribute_set_name">Default</data> + <data key="sort_order">0</data> + </entity> +</entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml index 697648cedb7ba..3ef78a3fe8f41 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml @@ -14,6 +14,7 @@ <element name="advancedPricingCloseButton" type="button" selector=".product_form_product_form_advanced_pricing_modal button.action-close" timeout="30"/> <element name="productTierPriceWebsiteSelect" type="select" selector="[name='product[tier_price][{{var1}}][website_id]']" parameterized="true"/> <element name="productTierPriceCustGroupSelect" type="select" selector="[name='product[tier_price][{{var1}}][cust_group]']" parameterized="true"/> + <element name="productTierPriceCustGroupSelectOptions" type="select" selector="[name='product[tier_price][{{var1}}][cust_group]'] option" parameterized="true"/> <element name="productTierPriceQtyInput" type="input" selector="[name='product[tier_price][{{var1}}][price_qty]']" parameterized="true"/> <element name="productTierPriceValueTypeSelect" type="select" selector="[name='product[tier_price][{{var1}}][value_type]']" parameterized="true"/> <element name="productTierPriceFixedPriceInput" type="input" selector="[name='product[tier_price][{{var1}}][price]']" parameterized="true"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminOpenNewCatalogPriceRuleFormPageActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminOpenNewCatalogPriceRuleFormPageActionGroup.xml new file mode 100644 index 0000000000000..072e8b24b0336 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminOpenNewCatalogPriceRuleFormPageActionGroup.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="AdminOpenNewCatalogPriceRuleFormPageActionGroup"> + <amOnPage url="{{CatalogRuleNewPage.url}}" stepKey="openNewCatalogPriceRulePage" /> + <waitForPageLoad stepKey="waitForPageLoad" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCatalogPriceRuleFormActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCatalogPriceRuleFormActionGroup.xml new file mode 100644 index 0000000000000..93a2a8a610951 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCatalogPriceRuleFormActionGroup.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="AssertCustomerGroupNotOnCatalogPriceRuleFormActionGroup"> + <arguments> + <argument name="customerGroup" type="entity" /> + </arguments> + <grabMultiple selector="{{AdminNewCatalogPriceRule.customerGroupsOptions}}" stepKey="customerGroups" /> + <assertNotContains stepKey="assertCustomerGroupNotInOptions"> + <actualResult type="variable">customerGroups</actualResult> + <expectedResult type="string">{{customerGroup.code}}</expectedResult> + </assertNotContains> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Page/CatalogRuleNewPage.xml b/app/code/Magento/CatalogRule/Test/Mftf/Page/CatalogRuleNewPage.xml new file mode 100644 index 0000000000000..ad3e40b37c5b0 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/Page/CatalogRuleNewPage.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="CatalogRuleNewPage" url="catalog_rule/promo_catalog/new/" module="Magento_CatalogRule" area="admin"> + <section name="AdminNewCatalogPriceRule"/> + </page> +</pages> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml new file mode 100644 index 0000000000000..75223fcfc4c4b --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml @@ -0,0 +1,17 @@ +<?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="DeleteCustomerGroupTest"> + <actionGroup ref="AdminOpenNewCatalogPriceRuleFormPageActionGroup" stepKey="openNewCatalogPriceRuleForm" /> + <actionGroup ref="AssertCustomerGroupNotOnCatalogPriceRuleFormActionGroup" stepKey="assertCustomerGroupNotOnCatalogPriceRuleForm"> + <argument name="customerGroup" value="$$customerGroup$$" /> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminOpenCustomerEditPageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminOpenCustomerEditPageActionGroup.xml new file mode 100644 index 0000000000000..8e6b56b19d674 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminOpenCustomerEditPageActionGroup.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="AdminOpenCustomerEditPageActionGroup"> + <arguments> + <argument name="customerId" type="string" /> + </arguments> + <amOnPage url="{{AdminEditCustomerPage.url(customerId)}}" stepKey="openCustomerEditPage" /> + <waitForPageLoad stepKey="waitForPageLoad" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotInGridActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotInGridActionGroup.xml new file mode 100644 index 0000000000000..26c4f23fc9a77 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotInGridActionGroup.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="AssertCustomerGroupNotInGridActionGroup"> + <arguments> + <argument name="customerGroup" type="entity" /> + </arguments> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="cleanFilters"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openFiltersSectionOnCustomerGroupIndexPage"/> + <fillField userInput="{{customerGroup.code}}" selector="{{AdminDataGridHeaderSection.filterFieldInput('customer_group_code')}}" stepKey="fillNameFieldOnFiltersSection"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickApplyFiltersButton"/> + <see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="assertDataGridEmptyMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnProductFormActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnProductFormActionGroup.xml new file mode 100644 index 0000000000000..94e01db5c1ff8 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnProductFormActionGroup.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="AssertCustomerGroupNotOnProductFormActionGroup"> + <arguments> + <argument name="customerGroup" type="entity" /> + </arguments> + <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickOnAdvancedPricingButton"/> + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="waitForCustomerGroupPriceAddButton"/> + <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="addCustomerGroupAllGroupsQty1PriceDiscountAnd10percent"/> + <grabMultiple selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelectOptions('0')}}" stepKey="customerGroups" /> + <assertNotContains stepKey="assertCustomerGroupNotInOptions"> + <actualResult type="variable">customerGroups</actualResult> + <expectedResult type="string">{{customerGroup.code}}</expectedResult> + </assertNotContains> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupOnCustomerFormActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupOnCustomerFormActionGroup.xml new file mode 100644 index 0000000000000..2c8e0081e5e90 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertCustomerGroupOnCustomerFormActionGroup.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="AssertCustomerGroupOnCustomerFormActionGroup"> + <arguments> + <argument name="customerGroup" type="entity" /> + </arguments> + <click selector="{{AdminCustomerAccountInformationSection.accountInformationTab}}" stepKey="clickOnAccountInfoTab" /> + <waitForPageLoad stepKey="waitForPageLoad" /> + <seeOptionIsSelected userInput="{{customerGroup.code}}" selector="{{AdminCustomerAccountInformationSection.group}}" stepKey="verifyNeededCustomerGroupSelected" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml index 06c23a2864984..f561e413a01f1 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml @@ -46,6 +46,19 @@ <data key="website_id">0</data> <requiredEntity type="address">US_Address_TX</requiredEntity> </entity> + <entity name="UsCustomerAssignedToNewCustomerGroup" type="customer"> + <var key="group_id" entityKey="id" entityType="customerGroup" /> + <data key="default_billing">true</data> + <data key="default_shipping">true</data> + <data key="email" unique="prefix">John.Doe@example.com</data> + <data key="firstname">John</data> + <data key="lastname">Doe</data> + <data key="fullname">John Doe</data> + <data key="password">pwdTest123!</data> + <data key="store_id">0</data> + <data key="website_id">0</data> + <requiredEntity type="address">US_Address_TX</requiredEntity> + </entity> <entity name="Simple_US_Customer_Incorrect_Name" type="customer"> <data key="group_id">1</data> <data key="default_billing">true</data> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml index c7c40d8170f3b..a085a67167f60 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml @@ -8,93 +8,48 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="DeleteCustomerGroup"> + <test name="DeleteCustomerGroupTest"> <annotations> - <title value="Delete customer group group"/> + <title value="Delete customer group entity test"/> <description value="Delete a customer group"/> <stories value="Delete Customer Group"/> + <testCaseId value="MC-14590" /> <group value="customers"/> <group value="mtf_migrated"/> </annotations> <before> - <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + <createData entity="CustomCustomerGroup" stepKey="customerGroup" /> + <createData entity="UsCustomerAssignedToNewCustomerGroup" stepKey="customer"> + <requiredEntity createDataKey="customerGroup" /> + </createData> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> <actionGroup ref="logout" stepKey="logout"/> </after> - <actionGroup ref="AdminCreateCustomerGroupActionGroup" stepKey="createCustomerGroup"> - <argument name="groupName" value="{{CustomerGroupChange.code}}"/> - <argument name="taxClass" value="{{CustomerGroupChange.tax_class_name}}"/> - </actionGroup> - <actionGroup ref="NavigateToAllCustomerPage" stepKey="navToCustomersCreate"/> - <actionGroup ref="AdminFilterCustomerByName" stepKey="filterCustomer"> - <argument name="customerName" value="{{Simple_US_Customer.fullname}}"/> - </actionGroup> - <actionGroup ref="AdminSelectCustomerByEmail" stepKey="selectCustomer"> - <argument name="customerEmail" value="$$createCustomer.email$$"/> - </actionGroup> - <actionGroup ref="SetCustomerGroupForSelectedCustomersViaGrid" stepKey="setCustomerGroup"> - <argument name="groupName" value="{{CustomerGroupChange.code}}"/> - </actionGroup> - <actionGroup ref="AdminFilterCustomerByName" stepKey="filterCustomerAfterGroupChange"> - <argument name="customerName" value="{{Simple_US_Customer.fullname}}"/> - </actionGroup> - <actionGroup ref="VerifyCustomerGroupForCustomer" stepKey="verifyCustomerGroupSet"> - <argument name="customerEmail" value="$$createCustomer.email$$"/> - <argument name="groupName" value="{{CustomerGroupChange.code}}"/> - </actionGroup> <!--Customer Group success delete message--> <actionGroup ref="AdminDeleteCustomerGroupActionGroup" stepKey="deleteCustomerGroup"> - <argument name="customerGroupName" value="{{CustomerGroupChange.code}}"/> + <argument name="customerGroupName" value="$$customerGroup.code$$"/> + </actionGroup> + <actionGroup ref="AssertCustomerGroupNotInGridActionGroup" stepKey="assertCustomerGroupNotInGrid"> + <argument name="customerGroup" value="$$customerGroup$$" /> </actionGroup> - <!--Customer Group is not in grid--> - <actionGroup ref="NavigateToCustomerGroupPage" stepKey="navToCustomerGroupPage"/> - - <!--Customer Group changed to "General" on customer form--> - <actionGroup ref="NavigateToAllCustomerPage" stepKey="navToCustomers"/> - <actionGroup ref="AdminFilterCustomerByName" stepKey="filterCustomerAfterGroupDelete"> - <argument name="customerName" value="{{Simple_US_Customer.fullname}}"/> + <actionGroup ref="AdminOpenCustomerEditPageActionGroup" stepKey="openCustomerEditPage"> + <argument name="customerId" value="$$customer.id$$" /> </actionGroup> - <actionGroup ref="AdminSelectCustomerByEmail" stepKey="selectCustomerAfterGroupDelete"> - <argument name="customerEmail" value="$$createCustomer.email$$"/> + + <actionGroup ref="AssertCustomerGroupOnCustomerFormActionGroup" stepKey="assertCustomerGroupOnCustomerForm"> + <argument name="customerGroup" value="GeneralCustomerGroup" /> </actionGroup> - <actionGroup ref="VerifyCustomerGroupForCustomer" stepKey="verifyGeneralGroupSet"> - <argument name="customerEmail" value="$$createCustomer.email$$"/> - <argument name="groupName" value="{{GeneralCustomerGroup.code}}"/> + + <actionGroup ref="AdminOpenNewProductFormPageActionGroup" stepKey="openNewProductForm" /> + + <actionGroup ref="AssertCustomerGroupNotOnProductFormActionGroup" stepKey="assertCustomerGroupNotOnProductForm"> + <argument name="customerGroup" value="$$customerGroup$$" /> </actionGroup> - - <!--Go to New Product page, add check custom customer group values--> - <amOnPage url="{{AdminProductCreatePage.url('4', 'simple')}}" stepKey="goToCreateSimpleProductPage"/> - <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickOnAdvancedPricingButton"/> - <waitForElement selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" - stepKey="waitForCustomerGroupPriceAddButton"/> - <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" - stepKey="addCustomerGroupAllGroupsQty1PriceDiscountAnd10percent"/> - <waitForElement selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" - stepKey="waitForSelectCustomerGroupNameAttribute2"/> - <dontSee selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" - userInput="{{CustomerGroupChange.code}}" - stepKey="seeProductTierPriceCustomerGroupInput"/> - - <!--Go to Catalog price rule page, add check custom customer group values--> - <amOnPage stepKey="goToPriceRulePage" url="{{CatalogRulePage.url}}"/> - <waitForPageLoad stepKey="waitForPriceRulePage"/> - <click stepKey="addNewRule" selector="{{AdminGridMainControls.add}}"/> - <dontSee selector="{{AdminNewCatalogPriceRule.customerGroups}}" - userInput="{{CustomerGroupChange.code}}" - stepKey="dontSeeCatalogPriceRuleCustomerGroups"/> - - <!--Go to Cart price rule page, add check custom customer group values--> - <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> - <waitForPageLoad stepKey="waitForRulesPage"/> - <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> - <dontSee selector="{{AdminCartPriceRulesFormSection.customerGroups}}" - userInput="{{CustomerGroupChange.code}}" - stepKey="dontSeeCartPriceRuleCustomerGroups"/> </test> </tests> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminOpenNewCartPriceRuleFormPageActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminOpenNewCartPriceRuleFormPageActionGroup.xml new file mode 100644 index 0000000000000..8cb958c9d9304 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminOpenNewCartPriceRuleFormPageActionGroup.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="AdminOpenNewCartPriceRuleFormPageActionGroup"> + <amOnPage url="{{PriceRuleNewPage.url}}" stepKey="openNewCartPriceRulePage" /> + <waitForPageLoad stepKey="waitForPageLoad" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCartPriceRuleFormActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCartPriceRuleFormActionGroup.xml new file mode 100644 index 0000000000000..98a094aea77ac --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AssertCustomerGroupNotOnCartPriceRuleFormActionGroup.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="AssertCustomerGroupNotOnCartPriceRuleFormActionGroup"> + <arguments> + <argument name="customerGroup" type="entity" /> + </arguments> + <grabMultiple selector="{{AdminCartPriceRulesFormSection.customerGroupsOptions}}" stepKey="customerGroups" /> + <assertNotContains stepKey="assertCustomerGroupNotInOptions"> + <actualResult type="variable">customerGroups</actualResult> + <expectedResult type="string">{{customerGroup.code}}</expectedResult> + </assertNotContains> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml index c8da82407457d..8af28a7fcb33e 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml @@ -18,6 +18,7 @@ <element name="ruleName" type="input" selector="input[name='name']"/> <element name="websites" type="multiselect" selector="select[name='website_ids']"/> <element name="customerGroups" type="multiselect" selector="select[name='customer_group_ids']"/> + <element name="customerGroupsOptions" type="multiselect" selector="select[name='customer_group_ids'] option"/> <element name="coupon" type="select" selector="select[name='coupon_type']"/> <element name="couponCode" type="input" selector="input[name='coupon_code']"/> <element name="useAutoGeneration" type="checkbox" selector="input[name='use_auto_generation']"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml new file mode 100644 index 0000000000000..77ee270b3bcaa --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/DeleteCustomerGroupTest.xml @@ -0,0 +1,17 @@ +<?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="DeleteCustomerGroupTest"> + <actionGroup ref="AdminOpenNewCartPriceRuleFormPageActionGroup" stepKey="openNewCartPriceRuleForm" /> + <actionGroup ref="AssertCustomerGroupNotOnCartPriceRuleFormActionGroup" stepKey="assertCustomerGroupNotOnCartPriceRuleForm"> + <argument name="customerGroup" value="$$customerGroup$$" /> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerGroupEntityTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerGroupEntityTest.xml index cffbbca8ad5cb..4251a1c5ee9c5 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerGroupEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerGroupEntityTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Customer\Test\TestCase\DeleteCustomerGroupEntityTest" summary="Delete Customer Group" ticketId="MAGETWO-25243"> <variation name="DeleteCustomerGroupEntityTestVariation1"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="customer/dataset" xsi:type="string">customer_with_new_customer_group</data> <data name="customer/data/group_id/dataset" xsi:type="string">default</data> <data name="defaultCustomerGroup/dataset" xsi:type="string">General</data> From 26412e9c5c3905b85bd3e94ea8aa82b0d172b529 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Sun, 21 Apr 2019 23:40:21 -0500 Subject: [PATCH 590/603] GraphQL-604: [Test coverage] End to tests for customer checkout workflow --- .../QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php | 3 +++ .../QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php | 2 ++ .../Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php index 142542e7b6aa5..481bad090dac1 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForCustomer.php @@ -47,6 +47,9 @@ public function __construct( } /** + * Create empty cart for customer + * + * @param int $customerId * @param string|null $predefinedMaskedQuoteId * @return string */ diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php index 99eef31e64a47..a6396ed6352ab 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateEmptyCartForGuest.php @@ -47,6 +47,8 @@ public function __construct( } /** + * Create empty cart for guest + * * @param string|null $predefinedMaskedQuoteId * @return string */ diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php index 9a559eda6ee64..f020527d958e4 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php @@ -72,6 +72,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } /** + * Validate masked id + * * @param string $maskedId * @throws GraphQlAlreadyExistsException * @throws GraphQlInputException @@ -88,6 +90,8 @@ private function validateMaskedId(string $maskedId): void } /** + * Check is quote with such maskedId already exists + * * @param string $maskedId * @return bool */ From 63c5db6ffeddefe8368e5ad7a2ba73b4dcba1afb Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 22 Apr 2019 16:02:53 +0300 Subject: [PATCH 591/603] MC-15406: [FT] [MFTF] StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest fails because of bad design --- .../Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml index f1e15aa5750dc..fda92810a13be 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminCreateStoreViewActionGroup.xml @@ -35,6 +35,13 @@ <remove keyForRemoval="seeSavedMessage"/> </actionGroup> + <!--Save the Store view--> + <actionGroup name="AdminCreateStoreViewActionSaveGroup"> + <waitForLoadingMaskToDisappear stepKey="waitForGridLoad"/> + <waitForElementVisible selector="{{AdminStoresGridSection.websiteFilterTextField}}" stepKey="waitForStoreGridToReload2"/> + <see userInput="You saved the store view." stepKey="seeSavedMessage" /> + </actionGroup> + <actionGroup name="navigateToAdminContentManagementPage"> <amOnPage url="{{AdminContentManagementPage.url}}" stepKey="navigateToConfigurationPage"/> <waitForPageLoad stepKey="waitForPageLoad1"/> @@ -58,4 +65,4 @@ <waitForElementVisible selector="{{errorMessageSelector}}" stepKey="waitForErrorMessage"/> <see selector="{{errorMessageSelector}}" userInput="{{errorMessage}}" stepKey="seeErrorMessage"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> From 8674fa400070f036ebaaa72557afaa5ca778f0c0 Mon Sep 17 00:00:00 2001 From: Iryna Lagno <ilagno@adobe.com> Date: Fri, 19 Apr 2019 14:01:45 -0500 Subject: [PATCH 592/603] MAGETWO-99210: Magento\Install\Test\TestCase\InstallTest is failing on php 7.1 -revert MQE-1352: bug fix in dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php --- .../lib/Magento/Mtf/Util/Command/File/Export/Reader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php index 79dd435ada7e6..d7336b51a18e2 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php @@ -74,7 +74,7 @@ private function getFiles() $serializedFiles = $this->transport->read(); $this->transport->close(); // phpcs:ignore Magento2.Security.InsecureFunction - return unserialize($serializedFiles); + return unserialize($serializedFiles, ['allowed_classes' => false]); } /** From 56ff6ac73308a66084ffe72b980680bba88f6d9d Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Mon, 22 Apr 2019 09:50:26 -0500 Subject: [PATCH 593/603] MC-15917: Create 'applyCouponToCart' and 'removeCouponFromCart' scenarios for benchmark --- setup/performance-toolkit/benchmark.jmx | 1157 +++++++++++++++++------ 1 file changed, 877 insertions(+), 280 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 55cdf7379cc5e..5521f7024722b 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -374,6 +374,11 @@ <stringProp name="Argument.value">${__P(graphqlAddSimpleProductToCartPercentage,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> + <elementProp name="graphqlApplyCouponToCartPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlApplyCouponToCartPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlApplyCouponToCartPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> <elementProp name="graphqlCatalogBrowsingByGuestPercentage" elementType="Argument"> <stringProp name="Argument.name">graphqlCatalogBrowsingByGuestPercentage</stringProp> <stringProp name="Argument.value">${__P(graphqlCatalogBrowsingByGuestPercentage,0)}</stringProp> @@ -449,6 +454,11 @@ <stringProp name="Argument.value">${__P(graphqlRemoveConfigurableProductFromCartPercentage,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> + <elementProp name="graphqlRemoveCouponFromCartPercentage" elementType="Argument"> + <stringProp name="Argument.name">graphqlRemoveCouponFromCartPercentage</stringProp> + <stringProp name="Argument.value">${__P(graphqlRemoveCouponFromCartPercentage,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> <elementProp name="graphqlRemoveSimpleProductFromCartPercentage" elementType="Argument"> <stringProp name="Argument.name">graphqlRemoveSimpleProductFromCartPercentage</stringProp> <stringProp name="Argument.value">${__P(graphqlRemoveSimpleProductFromCartPercentage,0)}</stringProp> @@ -41121,7 +41131,649 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Empty Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1901638450">{"data":{"cart":{"items":[]}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Billing Address On Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_billing_address_on_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1147076914">{"data":{"setBillingAddressOnCart":{"cart":{"billing_address":{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"BILLING"}}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Add Simple Product To Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlAddSimpleProductToCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "GraphQL Add Simple Product To Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("simple_products_list").size()); +product = props.get("simple_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Simple Product To Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_simple_product_to_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1421843282">addSimpleProductsToCart</stringProp> + <stringProp name="-1173443935">"sku":"${product_sku}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Add Configurable Product To Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlAddConfigurableProductToCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "GraphQL Add Configurable Product To Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("configurable_products_list").size()); +product = props.get("configurable_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract Configurable Product option" enabled="true"> + <stringProp name="VAR">product_option</stringProp> + <stringProp name="JSONPATH">$.data.products.items[0].variants[0].product.sku</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/extract_configurable_product_option.jmx</stringProp></com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Configurable Product To Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_configurable_product_to_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1421843282">addConfigurableProductsToCart</stringProp> + <stringProp name="675049292">"sku":"${product_option}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Update Simple Product Qty In Cart" enabled="true"> + <intProp name="ThroughputController.style">1</intProp> + <boolProp name="ThroughputController.perThread">false</boolProp> + <intProp name="ThroughputController.maxThroughput">1</intProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlUpdateSimpleProductQtyInCartPercentage}</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> + <hashTree> + <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> + <stringProp name="script"> +var testLabel = "${testLabel}" ? " (${testLabel})" : ""; +if (testLabel + && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' +) { + if (sampler.getName().indexOf(testLabel) == -1) { + sampler.setName(sampler.getName() + testLabel); + } +} else if (sampler.getName().indexOf("SetUp - ") == -1) { + sampler.setName("SetUp - " + sampler.getName()); +} + </stringProp> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> + <stringProp name="BeanShellSampler.query"> + vars.put("testLabel", "GraphQL Update Simple Product Qty In Cart"); + </stringProp> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">*/*</stringProp> + </elementProp> + </collectionProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = new Random(); +if (${seedForRandom} > 0) { + random.setSeed(${seedForRandom} + ${__threadNum}); +} + +vars.putObject("randomIntGenerator", random); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">quote_id</stringProp> + <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> + <stringProp name="BeanShellSampler.query"> +import java.util.Random; + +Random random = vars.getObject("randomIntGenerator"); +number = random.nextInt(props.get("simple_products_list").size()); +product = props.get("simple_products_list").get(number); + +vars.put("product_url_key", product.get("url_key")); +vars.put("product_id", product.get("id")); +vars.put("product_name", product.get("title")); +vars.put("product_uenc", product.get("uenc")); +vars.put("product_sku", product.get("sku")); + </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Simple Product To Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_simple_product_to_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1421843282">addSimpleProductsToCart</stringProp> + <stringProp name="-1173443935">"sku":"${product_sku}"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> @@ -41146,27 +41798,35 @@ vars.putObject("randomIntGenerator", random); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_empty_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1901638450">{"data":{"cart":{"items":[]}}}</stringProp> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">8</intProp> + <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Set Billing Address On Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product qty In Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n setBillingAddressOnCart(\n input: {\n cart_id: \"${quote_id}\"\n billing_address: {\n address: {\n firstname: \"test firstname\"\n lastname: \"test lastname\"\n company: \"test company\"\n street: [\"test street 1\", \"test street 2\"]\n city: \"test city\"\n region: \"test region\"\n postcode: \"887766\"\n country_code: \"US\"\n telephone: \"88776655\"\n save_in_address_book: false\n }\n }\n }\n ) {\n cart {\n billing_address {\n firstname\n lastname\n company\n street\n city\n postcode\n telephone\n country {\n code\n label\n }\n address_type\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41185,12 +41845,12 @@ vars.putObject("randomIntGenerator", random); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/set_billing_address_on_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/update_simple_product_qty_in_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1147076914">{"data":{"setBillingAddressOnCart":{"cart":{"billing_address":{"firstname":"test firstname","lastname":"test lastname","company":"test company","street":["test street 1","test street 2"],"city":"test city","postcode":"887766","telephone":"88776655","country":{"code":"US","label":"US"},"address_type":"BILLING"}}}}}</stringProp> + <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -41201,11 +41861,11 @@ vars.putObject("randomIntGenerator", random); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Add Simple Product To Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Update Configurable Product Qty In Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlAddSimpleProductToCartPercentage}</stringProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlUpdateConfigurableProductQtyInCartPercentage}</stringProp> <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> <hashTree> <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> @@ -41226,7 +41886,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "GraphQL Add Simple Product To Cart"); + vars.put("testLabel", "GraphQL Update Configurable Product Qty In Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -41311,13 +41971,13 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> <stringProp name="BeanShellSampler.query"> import java.util.Random; Random random = vars.getObject("randomIntGenerator"); -number = random.nextInt(props.get("simple_products_list").size()); -product = props.get("simple_products_list").get(number); +number = random.nextInt(props.get("configurable_products_list").size()); +product = props.get("configurable_products_list").get(number); vars.put("product_url_key", product.get("url_key")); vars.put("product_id", product.get("id")); @@ -41328,16 +41988,16 @@ vars.put("product_sku", product.get("sku")); <stringProp name="BeanShellSampler.filename"/> <stringProp name="BeanShellSampler.parameters"/> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Simple Product To Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41356,93 +42016,36 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_simple_product_to_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1421843282">addSimpleProductsToCart</stringProp> - <stringProp name="-1173443935">"sku":"${product_sku}"</stringProp> + <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> - </hashTree> - </hashTree> - - - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Add Configurable Product To Cart" enabled="true"> - <intProp name="ThroughputController.style">1</intProp> - <boolProp name="ThroughputController.perThread">false</boolProp> - <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlAddConfigurableProductToCartPercentage}</stringProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> - <hashTree> - <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> - <stringProp name="script"> -var testLabel = "${testLabel}" ? " (${testLabel})" : ""; -if (testLabel - && sampler.getClass().getName() == 'org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy' -) { - if (sampler.getName().indexOf(testLabel) == -1) { - sampler.setName(sampler.getName() + testLabel); - } -} else if (sampler.getName().indexOf("SetUp - ") == -1) { - sampler.setName("SetUp - " + sampler.getName()); -} - </stringProp> - <stringProp name="scriptLanguage">javascript</stringProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/setup_label.jmx</stringProp></JSR223PreProcessor> - <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> - <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "GraphQL Add Configurable Product To Cart"); - </stringProp> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - </BeanShellSampler> - <hashTree/> - <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> - <collectionProp name="HeaderManager.headers"> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Content-Type</stringProp> - <stringProp name="Header.value">application/json</stringProp> - </elementProp> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Accept</stringProp> - <stringProp name="Header.value">*/*</stringProp> - </elementProp> - </collectionProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/api/header_manager_before_token.jmx</stringProp></HeaderManager> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract Configurable Product option" enabled="true"> + <stringProp name="VAR">product_option</stringProp> + <stringProp name="JSONPATH">$.data.products.items[0].variants[0].product.sku</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/extract_configurable_product_option.jmx</stringProp></com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> <hashTree/> + </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Init Random Generator" enabled="true"> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/init_random_generator_setup.jmx</stringProp> - <stringProp name="BeanShellSampler.query"> -import java.util.Random; - -Random random = new Random(); -if (${seedForRandom} > 0) { - random.setSeed(${seedForRandom} + ${__threadNum}); -} - -vars.putObject("randomIntGenerator", random); - </stringProp> - <stringProp name="BeanShellSampler.filename"/> - <stringProp name="BeanShellSampler.parameters"/> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - </BeanShellSampler> - <hashTree/> - - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Create Empty Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Configurable Product To Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n createEmptyCart\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41461,20 +42064,13 @@ vars.putObject("randomIntGenerator", random); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/create_empty_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_configurable_product_to_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> - <stringProp name="VAR">quote_id</stringProp> - <stringProp name="JSONPATH">$.data.createEmptyCart</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1404608713">{"data":{"createEmptyCart":"</stringProp> + <stringProp name="1421843282">addConfigurableProductsToCart</stringProp> + <stringProp name="675049292">"sku":"${product_option}"</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -41483,33 +42079,13 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> - <stringProp name="BeanShellSampler.query"> -import java.util.Random; - -Random random = vars.getObject("randomIntGenerator"); -number = random.nextInt(props.get("configurable_products_list").size()); -product = props.get("configurable_products_list").get(number); - -vars.put("product_url_key", product.get("url_key")); -vars.put("product_id", product.get("id")); -vars.put("product_name", product.get("title")); -vars.put("product_uenc", product.get("uenc")); -vars.put("product_sku", product.get("sku")); - </stringProp> - <stringProp name="BeanShellSampler.filename"/> - <stringProp name="BeanShellSampler.parameters"/> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> - <hashTree/> - - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41528,36 +42104,35 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> + <stringProp name="VAR">item_id</stringProp> + <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> + <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> - - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract Configurable Product option" enabled="true"> - <stringProp name="VAR">product_option</stringProp> - <stringProp name="JSONPATH">$.data.products.items[0].variants[0].product.sku</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/extract_configurable_product_option.jmx</stringProp></com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> - </hashTree> + </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Configurable Product To Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product qty In Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41576,28 +42151,27 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_configurable_product_to_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/update_configurable_product_qty_in_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1421843282">addConfigurableProductsToCart</stringProp> - <stringProp name="675049292">"sku":"${product_option}"</stringProp> + <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> + <intProp name="Assertion.test_type">8</intProp> </ResponseAssertion> <hashTree/> </hashTree> </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Update Simple Product Qty In Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Remove Simple Product From Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlUpdateSimpleProductQtyInCartPercentage}</stringProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlRemoveSimpleProductFromCartPercentage}</stringProp> <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> <hashTree> <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> @@ -41618,7 +42192,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "GraphQL Update Simple Product Qty In Cart"); + vars.put("testLabel", "GraphQL Remove Simple Product From Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -41810,13 +42384,13 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product qty In Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Simple Product From Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41835,12 +42409,12 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/update_simple_product_qty_in_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_simple_product_from_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> + <stringProp name="1452665323">{"data":{"removeItemFromCart":{"cart":{"items":[]}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -41851,11 +42425,11 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Update Configurable Product Qty In Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Remove Configurable Product From Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlUpdateConfigurableProductQtyInCartPercentage}</stringProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlRemoveConfigurableProductFromCartPercentage}</stringProp> <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> <hashTree> <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> @@ -41876,7 +42450,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "GraphQL Update Configurable Product Qty In Cart"); + vars.put("testLabel", "GraphQL Remove Configurable Product From Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -42116,13 +42690,13 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product qty In Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Configurable Product From Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42141,12 +42715,12 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/update_configurable_product_qty_in_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_configurable_product_from_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> + <stringProp name="1452665323">{"data":{"removeItemFromCart":{"cart":{"items":[]}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -42157,11 +42731,11 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Remove Simple Product From Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Apply Coupon To Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlRemoveSimpleProductFromCartPercentage}</stringProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlApplyCouponToCartPercentage}</stringProp> <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> <hashTree> <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> @@ -42182,7 +42756,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "GraphQL Remove Simple Product From Cart"); + vars.put("testLabel", "GraphQL Apply Coupon To Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -42327,60 +42901,29 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">item_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> + <JSR223Sampler guiclass="TestBeanGUI" testclass="JSR223Sampler" testname="SetUp - Prepare Coupon Code Data" enabled="true"> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="parameters"/> + <stringProp name="filename"/> + <stringProp name="cacheKey"/> + <stringProp name="script">random = vars.getObject("randomIntGenerator"); + +var coupons = props.get("coupon_codes"); +number = random.nextInt(coupons.length); + +vars.put("coupon_code", coupons[number].code); + </stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/extract_coupon_code_setup.jmx</stringProp> + </JSR223Sampler> + <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Simple Product From Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Apply Coupon To Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n applyCouponToCart(input: {cart_id: \"${quote_id}\", coupon_code: \"${coupon_code}\"}) {\n cart {\n applied_coupon {\n code\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42399,12 +42942,12 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_simple_product_from_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/apply_coupon_to_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1452665323">{"data":{"removeItemFromCart":{"cart":{"items":[]}}}}</stringProp> + <stringProp name="1026466978">{"data":{"applyCouponToCart":{"cart":{"applied_coupon":{"code":"${coupon_code}"}}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -42415,11 +42958,11 @@ vars.put("product_sku", product.get("sku")); </hashTree> - <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Remove Configurable Product From Cart" enabled="true"> + <ThroughputController guiclass="ThroughputControllerGui" testclass="ThroughputController" testname="GraphQL Remove Coupon From Cart" enabled="true"> <intProp name="ThroughputController.style">1</intProp> <boolProp name="ThroughputController.perThread">false</boolProp> <intProp name="ThroughputController.maxThroughput">1</intProp> - <stringProp name="ThroughputController.percentThroughput">${graphqlRemoveConfigurableProductFromCartPercentage}</stringProp> + <stringProp name="ThroughputController.percentThroughput">${graphqlRemoveCouponFromCartPercentage}</stringProp> <stringProp name="TestPlan.comments">mpaf/tool/fragments/_system/scenario_controller_tmpl.jmx</stringProp></ThroughputController> <hashTree> <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Set Test Label" enabled="true"> @@ -42440,7 +42983,7 @@ if (testLabel <hashTree/> <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Label" enabled="true"> <stringProp name="BeanShellSampler.query"> - vars.put("testLabel", "GraphQL Remove Configurable Product From Cart"); + vars.put("testLabel", "GraphQL Remove Coupon From Cart"); </stringProp> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> </BeanShellSampler> @@ -42525,13 +43068,13 @@ vars.putObject("randomIntGenerator", random); <hashTree/> </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Configurable Product Data" enabled="true"> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Prepare Simple Product Data" enabled="true"> <stringProp name="BeanShellSampler.query"> import java.util.Random; Random random = vars.getObject("randomIntGenerator"); -number = random.nextInt(props.get("configurable_products_list").size()); -product = props.get("configurable_products_list").get(number); +number = random.nextInt(props.get("simple_products_list").size()); +product = props.get("simple_products_list").get(number); vars.put("product_url_key", product.get("url_key")); vars.put("product_id", product.get("id")); @@ -42542,64 +43085,16 @@ vars.put("product_sku", product.get("sku")); <stringProp name="BeanShellSampler.filename"/> <stringProp name="BeanShellSampler.parameters"/> <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/configurable_products_setup.jmx</stringProp></BeanShellSampler> - <hashTree/> - - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Configurable Product Details by name" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"query productDetailByName($name: String, $onServer: Boolean!) {\n products(filter: { name: { eq: $name } }) {\n items {\n id\n sku\n name\n ... on ConfigurableProduct {\n configurable_options {\n attribute_code\n attribute_id\n id\n label\n values {\n default_label\n label\n store_label\n use_default_value\n value_index\n }\n }\n variants {\n product {\n #fashion_color\n #fashion_size\n id\n media_gallery_entries {\n disabled\n file\n label\n position\n }\n sku\n stock_status\n }\n }\n }\n meta_title @include(if: $onServer)\n meta_keyword @include(if: $onServer)\n meta_description @include(if: $onServer)\n }\n }\n}","variables":{"name":"${product_name}","onServer":false},"operationName":"productDetailByName"}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_configurable_product_details_by_name.jmx</stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="1201352014">"sku":"${product_sku}","name":"${product_name}"</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract Configurable Product option" enabled="true"> - <stringProp name="VAR">product_option</stringProp> - <stringProp name="JSONPATH">$.data.products.items[0].variants[0].product.sku</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/extract_configurable_product_option.jmx</stringProp></com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/product_browsing_and_adding_items_to_the_cart/simple_products_setup.jmx</stringProp></BeanShellSampler> <hashTree/> - </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Configurable Product To Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Simple Product To Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42618,13 +43113,13 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_configurable_product_to_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/add_simple_product_to_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1421843282">addConfigurableProductsToCart</stringProp> - <stringProp name="675049292">"sku":"${product_option}"</stringProp> + <stringProp name="1421843282">addSimpleProductsToCart</stringProp> + <stringProp name="-1173443935">"sku":"${product_sku}"</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -42633,13 +43128,29 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Get Cart" enabled="true"> + <JSR223Sampler guiclass="TestBeanGUI" testclass="JSR223Sampler" testname="SetUp - Prepare Coupon Code Data" enabled="true"> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="parameters"/> + <stringProp name="filename"/> + <stringProp name="cacheKey"/> + <stringProp name="script">random = vars.getObject("randomIntGenerator"); + +var coupons = props.get("coupon_codes"); +number = random.nextInt(coupons.length); + +vars.put("coupon_code", coupons[number].code); + </stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/extract_coupon_code_setup.jmx</stringProp> + </JSR223Sampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Apply Coupon To Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n applyCouponToCart(input: {cart_id: \"${quote_id}\", coupon_code: \"${coupon_code}\"}) {\n cart {\n applied_coupon {\n code\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42658,35 +43169,27 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/get_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/apply_coupon_to_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> - <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract item id" enabled="true"> - <stringProp name="VAR">item_id</stringProp> - <stringProp name="JSONPATH">$.data.cart.items[0].id</stringProp> - <stringProp name="DEFAULT"/> - <stringProp name="VARIABLE"/> - <stringProp name="SUBJECT">BODY</stringProp> - </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> - <hashTree/> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-1486007127">{"data":{"cart":{"items":</stringProp> + <stringProp name="1026466978">{"data":{"applyCouponToCart":{"cart":{"applied_coupon":{"code":"${coupon_code}"}}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> + <intProp name="Assertion.test_type">8</intProp> </ResponseAssertion> <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Configurable Product From Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Coupon From Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeCouponFromCart(input: {cart_id: \"${quote_id}\"}) {\n cart {\n applied_coupon {\n code\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42705,12 +43208,12 @@ vars.put("product_sku", product.get("sku")); <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_configurable_product_from_cart.jmx</stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_coupon_from_cart.jmx</stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1452665323">{"data":{"removeItemFromCart":{"cart":{"items":[]}}}}</stringProp> + <stringProp name="-76201335">{"data":{"removeCouponFromCart":{"cart":{"applied_coupon":null}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -43743,6 +44246,100 @@ vars.put("product_sku", product.get("sku")); </ResponseAssertion> <hashTree/> </hashTree> + + <JSR223Sampler guiclass="TestBeanGUI" testclass="JSR223Sampler" testname="SetUp - Prepare Coupon Code Data" enabled="true"> + <stringProp name="scriptLanguage">javascript</stringProp> + <stringProp name="parameters"/> + <stringProp name="filename"/> + <stringProp name="cacheKey"/> + <stringProp name="script">random = vars.getObject("randomIntGenerator"); + +var coupons = props.get("coupon_codes"); +number = random.nextInt(coupons.length); + +vars.put("coupon_code", coupons[number].code); + </stringProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/common/extract_coupon_code_setup.jmx</stringProp> + </JSR223Sampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Apply Coupon To Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n applyCouponToCart(input: {cart_id: \"${quote_id}\", coupon_code: \"${coupon_code}\"}) {\n cart {\n applied_coupon {\n code\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/apply_coupon_to_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1026466978">{"data":{"applyCouponToCart":{"cart":{"applied_coupon":{"code":"${coupon_code}"}}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Remove Coupon From Cart" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeCouponFromCart(input: {cart_id: \"${quote_id}\"}) {\n cart {\n applied_coupon {\n code\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port">${graphql_port_number}</stringProp> + <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> + <stringProp name="HTTPSampler.response_timeout">200000</stringProp> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/remove_coupon_from_cart.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-76201335">{"data":{"removeCouponFromCart":{"cart":{"applied_coupon":null}}}}</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> </hashTree> </hashTree> From bbf4bbcd9d742d93a38924457d208255629fe8b8 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Mon, 22 Apr 2019 11:27:56 -0500 Subject: [PATCH 594/603] Minor fixes for magento/magento-functional-tests-migration#638: Convert ValidateEmailOnCheckoutTest to MFTF --- ...ClickAddToCartOnProductPageActionGroup.xml | 14 +++++ ...tEmailNoteMessageOnCheckoutActionGroup.xml | 18 ++++++ ...ailTooltipContentOnCheckoutActionGroup.xml | 19 ++++++ ...ValidationMessageOnCheckoutActionGroup.xml | 18 ++++++ .../Mftf/ActionGroup/CheckoutActionGroup.xml | 2 +- ...ontFillEmailFieldOnCheckoutActionGroup.xml | 19 ++++++ .../StorefrontOpenCheckoutPageActionGroup.xml | 14 +++++ ...ntCheckoutCheckoutCustomerLoginSection.xml | 22 +++++++ .../StorefrontValidateEmailOnCheckoutTest.xml | 54 +++++++++++++++++ .../Mftf/Test/ValidateEmailOnCheckoutTest.xml | 59 ------------------- 10 files changed, 179 insertions(+), 60 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontClickAddToCartOnProductPageActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailNoteMessageOnCheckoutActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailTooltipContentOnCheckoutActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailValidationMessageOnCheckoutActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillEmailFieldOnCheckoutActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenCheckoutPageActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutCheckoutCustomerLoginSection.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontValidateEmailOnCheckoutTest.xml delete mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/ValidateEmailOnCheckoutTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontClickAddToCartOnProductPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontClickAddToCartOnProductPageActionGroup.xml new file mode 100644 index 0000000000000..fb2065d228d5a --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontClickAddToCartOnProductPageActionGroup.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="StorefrontClickAddToCartOnProductPageActionGroup"> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addToCart" /> + <waitForElementVisible selector="{{StorefrontMessagesSection.success}}" stepKey="waitForSuccessMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailNoteMessageOnCheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailNoteMessageOnCheckoutActionGroup.xml new file mode 100644 index 0000000000000..c4fc753e73713 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailNoteMessageOnCheckoutActionGroup.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="AssertStorefrontEmailNoteMessageOnCheckoutActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="You can create an account after checkout." /> + </arguments> + <waitForElementVisible selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailNoteMessage}}" stepKey="waitForFormValidation"/> + <see selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailNoteMessage}}" userInput="{{message}}" stepKey="seeTheNoteMessageIsDisplayed"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailTooltipContentOnCheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailTooltipContentOnCheckoutActionGroup.xml new file mode 100644 index 0000000000000..f9c6771262ccc --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailTooltipContentOnCheckoutActionGroup.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="AssertStorefrontEmailTooltipContentOnCheckoutActionGroup"> + <arguments> + <argument name="content" type="string" defaultValue="We'll send your order confirmation here." /> + </arguments> + <waitForElementVisible selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailTooltipButton}}" stepKey="waitForTooltipButtonVisible" /> + <click selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailTooltipButton}}" stepKey="clickEmailTooltipButton" /> + <see selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailTooltipContent}}" userInput="{{content}}" stepKey="seeEmailTooltipContent" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailValidationMessageOnCheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailValidationMessageOnCheckoutActionGroup.xml new file mode 100644 index 0000000000000..14b96ed46ce6b --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontEmailValidationMessageOnCheckoutActionGroup.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="AssertStorefrontEmailValidationMessageOnCheckoutActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="Please enter a valid email address (Ex: johndoe@domain.com)." /> + </arguments> + <waitForElementVisible selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailErrorMessage}}" stepKey="waitForFormValidation"/> + <see selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailErrorMessage}}" userInput="{{message}}" stepKey="seeTheErrorMessageIsDisplayed"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml index b67b7451d5968..94c6e3fd76972 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml @@ -110,7 +110,7 @@ <argument name="paymentMethod" type="string"/> </arguments> <remove keyForRemoval="checkMessage"/> - <dontsee selector="{{CheckoutPaymentSection.paymentMethodByName(paymentMethod)}}" parametrized="true" stepKey="paymentMethodDoesNotAvailable"/> + <dontSee selector="{{CheckoutPaymentSection.paymentMethodByName(paymentMethod)}}" stepKey="paymentMethodDoesNotAvailable"/> </actionGroup> <!-- Logged in user checkout filling shipping section --> <actionGroup name="LoggedInUserCheckoutFillingShippingSectionActionGroup"> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillEmailFieldOnCheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillEmailFieldOnCheckoutActionGroup.xml new file mode 100644 index 0000000000000..fcac780a36776 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontFillEmailFieldOnCheckoutActionGroup.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="StorefrontFillEmailFieldOnCheckoutActionGroup"> + <arguments> + <argument name="email" type="string" /> + </arguments> + <fillField selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.email}}" userInput="{{email}}" stepKey="fillCustomerEmailField"/> + <doubleClick selector="{{StorefrontCheckoutCheckoutCustomerLoginSection.emailTooltipButton}}" stepKey="clickToMoveFocusFromEmailInput" /> + <waitForPageLoad stepKey="waitForPageLoad" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenCheckoutPageActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenCheckoutPageActionGroup.xml new file mode 100644 index 0000000000000..b18d476c02c65 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenCheckoutPageActionGroup.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="StorefrontOpenCheckoutPageActionGroup"> + <amOnPage url="{{CheckoutPage.url}}" stepKey="openCheckoutPage" /> + <waitForPageLoad stepKey="waitForCheckoutPageLoaded" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutCheckoutCustomerLoginSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutCheckoutCustomerLoginSection.xml new file mode 100644 index 0000000000000..5a3c309c6a1d4 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutCheckoutCustomerLoginSection.xml @@ -0,0 +1,22 @@ +<?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="StorefrontCheckoutCheckoutCustomerLoginSection"> + <element name="email" type="input" selector="form[data-role='email-with-possible-login'] input[name='username']" /> + <element name="emailNoteMessage" type="text" selector="//form[@data-role='email-with-possible-login']//div[input[@name='username']]//*[contains(@class, 'note')]" /> + <element name="emailErrorMessage" type="text" selector="//form[@data-role='email-with-possible-login']//div[input[@name='username']]//*[@id='customer-email-error']" /> + <element name="emailTooltipButton" type="button" selector="//form[@data-role='email-with-possible-login']//div[input[@name='username']]//*[contains(@class, 'action-help')]" /> + <element name="emailTooltipContent" type="text" selector="//form[@data-role='email-with-possible-login']//div[input[@name='username']]//*[contains(@class, 'field-tooltip-content')]" /> + <element name="password" type="input" selector="form[data-role='email-with-possible-login'] input[name='password']" /> + <element name="passwordNoteMessage" type="text" selector="//form[@data-role='email-with-possible-login']//div[input[@name='password']]//*[contains(@class, 'note')]" /> + <element name="submit" type="button" selector="form[data-role='email-with-possible-login'] button[type='submit']" /> + <element name="forgotPassword" type="button" selector="form[data-role='email-with-possible-login'] a.remind" /> + </section> +</sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontValidateEmailOnCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontValidateEmailOnCheckoutTest.xml new file mode 100644 index 0000000000000..1b27e1d53adad --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontValidateEmailOnCheckoutTest.xml @@ -0,0 +1,54 @@ +<?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="StorefrontValidateEmailOnCheckoutTest"> + <annotations> + <features value="Checkout"/> + <title value="Email validation for Guest on checkout flow"/> + <description value="Email validation for Guest on checkout flow"/> + <stories value="Guest Checkout"/> + <testCaseId value="MC-14695" /> + <group value="checkout"/> + <group value="shoppingCart"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <createData entity="SimpleTwo" stepKey="simpleProduct"/> + </before> + + <after> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + </after> + + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openProductStorefront"> + <argument name="productUrl" value="$$simpleProduct.custom_attributes[url_key]$$" /> + </actionGroup> + <actionGroup ref="StorefrontClickAddToCartOnProductPageActionGroup" stepKey="addToCartFromStorefrontProductPage" /> + + <actionGroup ref="StorefrontOpenCheckoutPageActionGroup" stepKey="openCheckoutPage" /> + <actionGroup ref="AssertStorefrontEmailTooltipContentOnCheckoutActionGroup" stepKey="assertEmailTooltipContent" /> + <actionGroup ref="AssertStorefrontEmailNoteMessageOnCheckoutActionGroup" stepKey="assertEmailNoteMessage" /> + + <actionGroup ref="StorefrontFillEmailFieldOnCheckoutActionGroup" stepKey="fillIncorrectEmailFirstAttempt"> + <argument name="email" value="John" /> + </actionGroup> + <actionGroup ref="AssertStorefrontEmailValidationMessageOnCheckoutActionGroup" stepKey="verifyValidationErrorMessageFirstAttempt" /> + + <actionGroup ref="StorefrontFillEmailFieldOnCheckoutActionGroup" stepKey="fillIncorrectEmailSecondAttempt"> + <argument name="email" value="johndoe#example.com" /> + </actionGroup> + <actionGroup ref="AssertStorefrontEmailValidationMessageOnCheckoutActionGroup" stepKey="verifyValidationErrorMessageSecondAttempt" /> + + <actionGroup ref="StorefrontFillEmailFieldOnCheckoutActionGroup" stepKey="fillIncorrectEmailThirdAttempt"> + <argument name="email" value="johndoe@example.c" /> + </actionGroup> + <actionGroup ref="AssertStorefrontEmailValidationMessageOnCheckoutActionGroup" stepKey="verifyValidationErrorMessageThirdAttempt" /> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/ValidateEmailOnCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/ValidateEmailOnCheckoutTest.xml deleted file mode 100644 index e41573ffbfc64..0000000000000 --- a/app/code/Magento/Checkout/Test/Mftf/Test/ValidateEmailOnCheckoutTest.xml +++ /dev/null @@ -1,59 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="ValidateEmailOnCheckoutTest"> - <annotations> - <features value="Checkout"/> - <title value="Guest Checkout"/> - <description value="Email validation for Guest on checkout flow"/> - <stories value="Email validation for Guest on checkout flow"/> - <group value="shoppingCart"/> - <group value="mtf_migrated"/> - </annotations> - <before> - <createData entity="SimpleTwo" stepKey="createSimpleProduct"/> - </before> - - <!--Go to product page--> - <amOnPage url="$$createSimpleProduct.custom_attributes[url_key]$$.html" stepKey="navigateToSimpleProductPage"/> - <waitForPageLoad stepKey="waitForCatalogPageLoad"/> - - <!--Add Product to Shopping Cart--> - <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addToCartFromStorefrontProductPage"> - <argument name="productName" value="$$createSimpleProduct.name$$"/> - </actionGroup> - - <!--Go to Checkout--> - <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask1"/> - - <!--Fill in the form fields for 1st variation, and check the validation message--> - <fillField selector="{{CheckoutShippingSection.email}}" userInput="johndoe" stepKey="setCustomerEmailVariation1"/> - <fillField selector="{{CheckoutShippingSection.firstName}}" userInput="John" stepKey="SetCustomerFirstNameVariation1"/> - <waitForPageLoad stepKey="waitforFormValidation1"/> - <see userInput="Please enter a valid email address (Ex: johndoe@domain.com)." stepKey="seeTheErrorMessageIsDisplayed1"/> - - <!--Fill in the form fields for 2nd variation, and check the validation message--> - <fillField selector="{{CheckoutShippingSection.email}}" userInput="johndoe#example.com" stepKey="setCustomerEmailVariation2"/> - <fillField selector="{{CheckoutShippingSection.firstName}}" userInput="John" stepKey="SetCustomerFirstNameVariation2"/> - <waitForPageLoad stepKey="waitForFormValidation2"/> - <see userInput="Please enter a valid email address (Ex: johndoe@domain.com)." stepKey="seeTheErrorMessageIsDisplayed2"/> - - <!--Fill in the form fields for 3rd variation, and check the validation message--> - <fillField selector="{{CheckoutShippingSection.email}}" userInput="johndoe@example.c" stepKey="setCustomerEmailVariation3"/> - <fillField selector="{{CheckoutShippingSection.firstName}}" userInput="John" stepKey="SetCustomerFirstNameVariation3"/> - <waitForPageLoad stepKey="waitForFormValidation3"/> - <see userInput="Please enter a valid email address (Ex: johndoe@domain.com)." stepKey="seeTheErrorMessageIsDisplayed3"/> - - <after> - <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> - </after> - </test> -</tests> From 83059746ee107e86f8046d78890556311bbd00cf Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@magento.com> Date: Mon, 22 Apr 2019 12:43:45 -0500 Subject: [PATCH 595/603] magento-engcom/magento2ce#2777: Fixed code style issues --- .../Model/Product/Gallery/CreateHandler.php | 2 ++ .../Entity/Collection/AbstractCollection.php | 20 ++++++++++--------- .../Model/Import/ProductTest.php | 1 + .../Magento/Framework/Data/Collection.php | 18 ++++++++--------- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php index d2ad6748a9f83..e06e85e90a2d8 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php @@ -230,6 +230,7 @@ public function getAttribute() * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @since 101.0.0 + * phpcs:disable Magento2.CodeAnalysis.EmptyBlock */ protected function processDeletedImages($product, array &$images) { @@ -400,6 +401,7 @@ protected function getUniqueFileName($file, $forTmp = false) $destinationFile = $forTmp ? $this->mediaDirectory->getAbsolutePath($this->mediaConfig->getTmpMediaPath($file)) : $this->mediaDirectory->getAbsolutePath($this->mediaConfig->getMediaPath($file)); + // phpcs:disable Magento2.Functions.DiscouragedFunction $destFile = dirname($file) . '/' . FileUploader::getNewFileName($destinationFile); } diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index 9129015c99c55..52f106a0475f5 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -16,6 +16,7 @@ /** * Entity/Attribute/Model - collection abstract * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @SuppressWarnings(PHPMD.TooManyFields) * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) @@ -188,6 +189,7 @@ public function __construct( * Initialize collection * * @return void + * phpcs:disable Magento2.CodeAnalysis.EmptyBlock */ protected function _construct() { @@ -298,7 +300,7 @@ public function getResource() /** * Set template object for the collection * - * @param \Magento\Framework\DataObject $object + * @param \Magento\Framework\DataObject $object * @return $this */ public function setObject($object = null) @@ -1371,8 +1373,8 @@ protected function _getAttributeFieldName($attributeCode) /** * Add attribute value table to the join if it wasn't added previously * - * @param string $attributeCode - * @param string $joinType inner|left + * @param string $attributeCode + * @param string $joinType inner|left * @return $this * @throws LocalizedException * @SuppressWarnings(PHPMD.NPathComplexity) @@ -1466,12 +1468,12 @@ protected function getEntityPkName(\Magento\Eav\Model\Entity\AbstractEntity $ent /** * Adding join statement to collection select instance * - * @param string $method - * @param object $attribute - * @param string $tableAlias - * @param array $condition - * @param string $fieldCode - * @param string $fieldAlias + * @param string $method + * @param object $attribute + * @param string $tableAlias + * @param array $condition + * @param string $fieldCode + * @param string $fieldAlias * @return $this */ protected function _joinAttributeToSelect($method, $attribute, $tableAlias, $condition, $fieldCode, $fieldAlias) 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 ceffbc6d138e5..70c16e05712b9 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -568,6 +568,7 @@ public function testSaveDatetimeAttribute() */ protected function getExpectedOptionsData(string $pathToFile, string $storeCode = ''): array { + // phpcs:disable Magento2.Functions.DiscouragedFunction $productData = $this->csvToArray(file_get_contents($pathToFile)); $expectedOptionId = 0; $expectedOptions = []; diff --git a/lib/internal/Magento/Framework/Data/Collection.php b/lib/internal/Magento/Framework/Data/Collection.php index e0781a25de146..128d3d8e9fd3d 100644 --- a/lib/internal/Magento/Framework/Data/Collection.php +++ b/lib/internal/Magento/Framework/Data/Collection.php @@ -392,7 +392,7 @@ public function getItemByColumnValue($column, $value) /** * Adding item to item array * - * @param \Magento\Framework\DataObject $item + * @param \Magento\Framework\DataObject $item * @return $this * @throws \Exception */ @@ -454,7 +454,7 @@ public function getAllIds() /** * Remove item from collection by item key * - * @param mixed $key + * @param mixed $key * @return $this */ public function removeItemByKey($key) @@ -542,8 +542,8 @@ public function each($objMethod, $args = []) /** * Setting data for all collection items * - * @param mixed $key - * @param mixed $value + * @param mixed $key + * @param mixed $value * @return $this */ public function setDataToAll($key, $value = null) @@ -563,7 +563,7 @@ public function setDataToAll($key, $value = null) /** * Set current page * - * @param int $page + * @param int $page * @return $this */ public function setCurPage($page) @@ -575,7 +575,7 @@ public function setCurPage($page) /** * Set collection page size * - * @param int $size + * @param int $size * @return $this */ public function setPageSize($size) @@ -587,8 +587,8 @@ public function setPageSize($size) /** * Set select order * - * @param string $field - * @param string $direction + * @param string $field + * @param string $direction * @return $this */ public function setOrder($field, $direction = self::SORT_ORDER_DESC) @@ -600,7 +600,7 @@ public function setOrder($field, $direction = self::SORT_ORDER_DESC) /** * Set collection item class name * - * @param string $className + * @param string $className * @return $this * @throws \InvalidArgumentException */ From 332c4b1af0c1d4123fb3a2e7957ec6111434c4ed Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Mon, 22 Apr 2019 20:46:50 -0500 Subject: [PATCH 596/603] Minor fixes for magento/magento-functional-tests-migration#382: Convert LockAdminUserWhenCreatingNewUserTest to MFTF - add test case id and move some files --- .../Mftf/Section/AdminLoginFormSection.xml | 1 - .../Test/Mftf/Section/AdminNewUserSection.xml | 23 ---- ...rInvalidCurrentUserPasswordActionGroup.xml | 35 ------ .../Security/Test/Mftf/Data/AdminUserData.xml | 18 --- .../AdminUserLockWhenCreatingNewUserTest.xml | 79 +++++++++++++ .../LockAdminUserWhenCreatingNewUserTest.xml | 110 ------------------ ...inClickSaveButtonOnUserFormActionGroup.xml | 14 +++ .../AdminCreateUserActionGroup.xml | 2 +- ...llNewUserFormRequiredFieldsActionGroup.xml | 31 +++++ .../AdminOpenNewUserPageActionGroup.xml | 14 +++ .../AssertAdminUserSaveMessageActionGroup.xml | 18 +++ .../Magento/User/Test/Mftf/Data/UserData.xml | 34 ++++++ .../Test/Mftf/Page/AdminNewUserPage.xml} | 5 +- .../Mftf/Section/AdminNewUserFormSection.xml | 30 +++++ .../Section/AdminUserFormMessagesSection.xml | 14 +++ 15 files changed, 238 insertions(+), 190 deletions(-) delete mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminNewUserSection.xml delete mode 100644 app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml delete mode 100644 app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml create mode 100644 app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenCreatingNewUserTest.xml delete mode 100644 app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminClickSaveButtonOnUserFormActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillNewUserFormRequiredFieldsActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenNewUserPageActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminUserSaveMessageActionGroup.xml rename app/code/Magento/{Backend/Test/Mftf/Page/AdminAddNewUserPage.xml => User/Test/Mftf/Page/AdminNewUserPage.xml} (61%) create mode 100644 app/code/Magento/User/Test/Mftf/Section/AdminNewUserFormSection.xml create mode 100644 app/code/Magento/User/Test/Mftf/Section/AdminUserFormMessagesSection.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml index 9239784393d29..bd65dea89abc2 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml @@ -13,6 +13,5 @@ <element name="password" type="input" selector="#login"/> <element name="signIn" type="button" selector=".actions .action-primary" timeout="30"/> <element name="forgotPasswordLink" type="button" selector=".action-forgotpassword" timeout="10"/> - <element name="error" type="text" selector=".message.message-error.error"/> </section> </sections> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminNewUserSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminNewUserSection.xml deleted file mode 100644 index a85229ad991d6..0000000000000 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminNewUserSection.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?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="AdminNewUserSection"> - <element name="username" type="input" selector="#user_username"/> - <element name="firstname" type="input" selector="#user_firstname"/> - <element name="lastname" type="input" selector="#user_lastname"/> - <element name="email" type="input" selector="#user_email"/> - <element name="password" type="input" selector="#user_password"/> - <element name="confirmation" type="input" selector="#user_confirmation"/> - <element name="currentPassword" type="input" selector="#user_current_password"/> - <element name="save" type="button" selector="#save"/> - <element name="userRoleTab" type="button" selector="#page_tabs_roles_section"/> - <element name="administratorRole" type="radio" selector="//*[@id='permissionsUserRolesGrid_table']//td[{{role}}]/input" parameterized="true"/> - </section> -</sections> diff --git a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml b/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml deleted file mode 100644 index 0992dd23c76f4..0000000000000 --- a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewUserInvalidCurrentUserPasswordActionGroup.xml +++ /dev/null @@ -1,35 +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="AdminNewUserInvalidCurrentUserPasswordActionGroup"> - <arguments> - <argument name="adminUser" type="string" /> - <argument name="adminFirstname" type="string" /> - <argument name="adminLastname" type="string" /> - <argument name="adminEmail" type="string" /> - <argument name="adminPassword" type="string" /> - <argument name="adminPasswordConfirmation" type="string" /> - <argument name="currentAdminPassword" type="string" /> - <argument name="adminUserRole" type="string"/> - </arguments> - <!-- Fill in all data according to data set (current password is incorrect). --> - <fillField selector="{{AdminNewUserSection.username}}" userInput="{{adminUser}}" stepKey="fillUser"/> - <fillField selector="{{AdminNewUserSection.firstname}}" userInput="{{adminFirstname}}" stepKey="fillFirstName"/> - <fillField selector="{{AdminNewUserSection.lastname}}" userInput="{{adminLastname}}" stepKey="fillLastName"/> - <fillField selector="{{AdminNewUserSection.email}}" userInput="{{adminEmail}}" stepKey="fillEmail"/> - <fillField selector="{{AdminNewUserSection.password}}" userInput="{{adminPassword}}" stepKey="fillPassword"/> - <fillField selector="{{AdminNewUserSection.confirmation}}" userInput="{{adminPasswordConfirmation}}" stepKey="fillPasswordConfirmation"/> - <fillField selector="{{AdminNewUserSection.currentPassword}}" userInput="{{currentAdminPassword}}" stepKey="fillCurrentUserPassword"/> - <scrollToTopOfPage stepKey="ScrollToTopOfPage"/> - <click selector="{{AdminNewUserSection.userRoleTab}}" stepKey="openUserRoleTab"/> - <click selector="{{adminUserRole}}" stepKey="assignRole"/> - <click selector="{{AdminNewUserSection.save}}" stepKey="saveNewUser"/> - <waitForPageLoad stepKey="waitForSaveResultLoad"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml b/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml deleted file mode 100644 index 1b3ec0ab351b9..0000000000000 --- a/app/code/Magento/Security/Test/Mftf/Data/AdminUserData.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?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="AdminUserData" type="admin"> - <data key="email" unique="prefix">John.Doe@example.com</data> - <data key="firstname">John</data> - <data key="username" unique="prefix">lockuser</data> - <data key="lastname">Doe</data> - <data key="password">pwdTest123!</data> - </entity> -</entities> diff --git a/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenCreatingNewUserTest.xml b/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenCreatingNewUserTest.xml new file mode 100644 index 0000000000000..4ceffd676313d --- /dev/null +++ b/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenCreatingNewUserTest.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="AdminUserLockWhenCreatingNewUserTest"> + <annotations> + <features value="Security"/> + <stories value="Runs Lock admin user when creating new user test."/> + <title value="Lock admin user when creating new user"/> + <description value="Runs Lock admin user when creating new user test."/> + <testCaseId value="MC-14383" /> + <severity value="CRITICAL"/> + <group value="security"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Log in to Admin Panel --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!-- Unlock Admin user --> + <magentoCLI command="admin:user:unlock {{DefaultAdminUser.username}}" stepKey="unlockAdminUser"/> + </after> + + <!-- Open Admin New User Page --> + <actionGroup ref="AdminOpenNewUserPageActionGroup" stepKey="openNewUserPage" /> + + <!-- Perform add new admin user 6 specified number of times. + "The password entered for the current user is invalid. Verify the password and try again." appears after each attempt.--> + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="failedSaveUserFirstAttempt"> + <argument name="user" value="NewAdminUserWrongCurrentPassword" /> + </actionGroup> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveFirstAttempt" /> + <actionGroup ref="AssertAdminUserSaveMessageActionGroup" stepKey="seeInvalidPasswordError"> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + <argument name="messageType" value="error" /> + </actionGroup> + + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="failedSaveUserSecondAttempt"> + <argument name="user" value="NewAdminUserWrongCurrentPassword" /> + </actionGroup> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveSecondAttempt" /> + + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="failedSaveUserThirdAttempt"> + <argument name="user" value="NewAdminUserWrongCurrentPassword" /> + </actionGroup> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveThirdAttempt" /> + + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="failedSaveUserFourthAttempt"> + <argument name="user" value="NewAdminUserWrongCurrentPassword" /> + </actionGroup> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveFourthAttempt" /> + + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="failedSaveUserFifthAttempt"> + <argument name="user" value="NewAdminUserWrongCurrentPassword" /> + </actionGroup> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveFifthAttempt" /> + + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="failedSaveUserSixthAttempt"> + <argument name="user" value="NewAdminUserWrongCurrentPassword" /> + </actionGroup> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveSixthAttempt" /> + + <!-- Check Error that account has been locked --> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeLockUserErrorMessage"> + <argument name="message" value="Your account is temporarily disabled. Please try again later." /> + </actionGroup> + + <!-- Try to login as admin and check error --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeLoginUserErrorMessage" /> + </test> +</tests> diff --git a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml deleted file mode 100644 index ec4dcd8dd0f6d..0000000000000 --- a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewUserTest.xml +++ /dev/null @@ -1,110 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="LockAdminUserWhenCreatingNewUserTest"> - <annotations> - <features value="Security"/> - <stories value="Runs Lock admin user when creating new user test."/> - <title value="Lock admin user when creating new user"/> - <description value="Runs Lock admin user when creating new user test."/> - <severity value="MAJOR"/> - <group value="security"/> - <group value="mtf_migrated"/> - </annotations> - <before> - <!-- Log in to Admin Panel --> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - </before> - <after> - <!-- Unlock Admin user --> - <magentoCLI command="admin:user:unlock {{_ENV.MAGENTO_ADMIN_USERNAME}}" stepKey="unlockAdminUser"/> - </after> - - <!-- Open Admin New User Page --> - <amOnPage url="{{AdminAddNewUserPage.url}}" stepKey="amOnNewAdminUserPage"/> - <waitForPageLoad stepKey="waitForNewAdminUserPageLoad"/> - - <!-- Perform add new admin user 6 specified number of times. - "The password entered for the current user is invalid. Verify the password and try again." appears after each attempt.--> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserFirstAttempt"> - <argument name="adminUser" value="{{AdminUserData.username}}" /> - <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> - <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> - <argument name="adminEmail" value="{{AdminUserData.email}}" /> - <argument name="adminPassword" value="{{AdminUserData.password}}" /> - <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> - <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> - <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> - </actionGroup> - <waitForPageLoad stepKey="waitForSaveResultLoad"/> - <see selector="{{AdminMessagesSection.error}}" userInput="The password entered for the current user is invalid. Verify the password and try again." - stepKey="seeInvalidPasswordError"/> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserSecondAttempt"> - <argument name="adminUser" value="{{AdminUserData.username}}" /> - <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> - <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> - <argument name="adminEmail" value="{{AdminUserData.email}}" /> - <argument name="adminPassword" value="{{AdminUserData.password}}" /> - <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> - <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> - <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> - </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserThirdAttempt"> - <argument name="adminUser" value="{{AdminUserData.username}}" /> - <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> - <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> - <argument name="adminEmail" value="{{AdminUserData.email}}" /> - <argument name="adminPassword" value="{{AdminUserData.password}}" /> - <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> - <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> - <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> - </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserFourthAttempt"> - <argument name="adminUser" value="{{AdminUserData.username}}" /> - <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> - <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> - <argument name="adminEmail" value="{{AdminUserData.email}}" /> - <argument name="adminPassword" value="{{AdminUserData.password}}" /> - <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> - <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> - <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> - </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserFifthAttempt"> - <argument name="adminUser" value="{{AdminUserData.username}}" /> - <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> - <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> - <argument name="adminEmail" value="{{AdminUserData.email}}" /> - <argument name="adminPassword" value="{{AdminUserData.password}}" /> - <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> - <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> - <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> - </actionGroup> - <actionGroup ref="AdminNewUserInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveUserSixthAttempt"> - <argument name="adminUser" value="{{AdminUserData.username}}" /> - <argument name="adminFirstname" value="{{AdminUserData.firstname}}" /> - <argument name="adminLastname" value="{{AdminUserData.lastname}}" /> - <argument name="adminEmail" value="{{AdminUserData.email}}" /> - <argument name="adminPassword" value="{{AdminUserData.password}}" /> - <argument name="adminPasswordConfirmation" value="{{AdminUserData.password}}" /> - <argument name="currentAdminPassword" value="{{AdminUserData.password}}INVALID" /> - <argument name="adminUserRole" value="{{AdminNewUserSection.administratorRole('1')}}" /> - </actionGroup> - - <!-- Check Error that account has been locked --> - <waitForPageLoad stepKey="wailtForSaveResultLoad"/> - <see selector="{{AdminLoginFormSection.error}}" userInput="Your account is temporarily disabled. Please try again later." stepKey="seeLockUserError"/> - - <!-- Try to login as admin and check error --> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> - <waitForPageLoad stepKey="waitForError"/> - <see selector="{{AdminLoginFormSection.error}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later" - stepKey="seeLoginUserError"/> - </test> -</tests> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminClickSaveButtonOnUserFormActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminClickSaveButtonOnUserFormActionGroup.xml new file mode 100644 index 0000000000000..e1edb16aba6ea --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminClickSaveButtonOnUserFormActionGroup.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="AdminClickSaveButtonOnUserFormActionGroup"> + <click selector="{{AdminNewUserFormSection.save}}" stepKey="saveNewUser"/> + <waitForPageLoad stepKey="waitForSaveResultLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateUserActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateUserActionGroup.xml index 303713132d2b0..5d51dcc610f78 100644 --- a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateUserActionGroup.xml +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateUserActionGroup.xml @@ -39,7 +39,7 @@ <argument name="role"/> <argument name="user" defaultValue="newAdmin"/> </arguments> - <amOnPage url="{{AdminEditUserPage.url}}" stepKey="navigateToNewUser"/> + <amOnPage url="{{AdminNewUserPage.url}}" stepKey="navigateToNewUser"/> <waitForPageLoad stepKey="waitForUsersPage" /> <fillField selector="{{AdminCreateUserSection.usernameTextField}}" userInput="{{user.username}}" stepKey="enterUserName" /> <fillField selector="{{AdminCreateUserSection.firstNameTextField}}" userInput="{{user.firstName}}" stepKey="enterFirstName" /> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillNewUserFormRequiredFieldsActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillNewUserFormRequiredFieldsActionGroup.xml new file mode 100644 index 0000000000000..87bf1e003931a --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillNewUserFormRequiredFieldsActionGroup.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminFillNewUserFormRequiredFieldsActionGroup"> + <arguments> + <argument name="user" type="entity" /> + </arguments> + <fillField selector="{{AdminNewUserFormSection.username}}" userInput="{{user.username}}" stepKey="fillUser"/> + <fillField selector="{{AdminNewUserFormSection.firstname}}" userInput="{{user.firstname}}" stepKey="fillFirstName"/> + <fillField selector="{{AdminNewUserFormSection.lastname}}" userInput="{{user.lastname}}" stepKey="fillLastName"/> + <fillField selector="{{AdminNewUserFormSection.email}}" userInput="{{user.email}}" stepKey="fillEmail"/> + <fillField selector="{{AdminNewUserFormSection.password}}" userInput="{{user.password}}" stepKey="fillPassword"/> + <fillField selector="{{AdminNewUserFormSection.passwordConfirmation}}" userInput="{{user.password_confirmation}}" stepKey="fillPasswordConfirmation"/> + <fillField selector="{{AdminNewUserFormSection.currentPassword}}" userInput="{{user.current_password}}" stepKey="fillCurrentUserPassword"/> + <scrollToTopOfPage stepKey="scrollToTopOfPage"/> + <click selector="{{AdminNewUserFormSection.userRoleTab}}" stepKey="openUserRoleTab"/> + <waitForPageLoad stepKey="waitForUserRoleTabOpened" /> + <click selector="{{AdminNewUserFormSection.resetFilter}}" stepKey="resetGridFilter" /> + <waitForPageLoad stepKey="waitForFiltersReset" /> + <fillField userInput="{{user.role}}" selector="{{AdminNewUserFormSection.roleFilterField}}" stepKey="fillRoleFilterField" /> + <click selector="{{AdminNewUserFormSection.search}}" stepKey="clickSearchButton" /> + <waitForPageLoad stepKey="waitForFiltersApplied" /> + <checkOption selector="{{AdminNewUserFormSection.roleRadiobutton(user.role)}}" stepKey="assignRole"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenNewUserPageActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenNewUserPageActionGroup.xml new file mode 100644 index 0000000000000..67aef9379faa8 --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenNewUserPageActionGroup.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="AdminOpenNewUserPageActionGroup"> + <amOnPage url="{{AdminNewUserPage.url}}" stepKey="amOnNewAdminUserPage"/> + <waitForPageLoad stepKey="waitForNewAdminUserPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminUserSaveMessageActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminUserSaveMessageActionGroup.xml new file mode 100644 index 0000000000000..db4f0a89348a9 --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AssertAdminUserSaveMessageActionGroup.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="AssertAdminUserSaveMessageActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="You saved the user." /> + <argument name="messageType" type="string" defaultValue="success" /> + </arguments> + <waitForElementVisible selector="{{AdminUserFormMessagesSection.messageByType(messageType)}}" stepKey="waitForMessage" /> + <see userInput="{{message}}" selector="{{AdminUserFormMessagesSection.messageByType(messageType)}}" stepKey="verifyMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/Data/UserData.xml b/app/code/Magento/User/Test/Mftf/Data/UserData.xml index d602f094ce4e5..e665736ae28f1 100644 --- a/app/code/Magento/User/Test/Mftf/Data/UserData.xml +++ b/app/code/Magento/User/Test/Mftf/Data/UserData.xml @@ -16,6 +16,40 @@ <data key="username" unique="suffix">username_</data> <data key="password" unique="suffix">password_</data> </entity> + <entity name="NewAdminUser" type="user"> + <data key="username" unique="suffix">admin</data> + <data key="firstname">John</data> + <data key="lastname">Doe</data> + <data key="email" unique="prefix">admin@example.com</data> + <data key="password">123123q</data> + <data key="password_confirmation">123123q</data> + <data key="interface_local">en_US</data> + <data key="interface_local_label">English (United States)</data> + <data key="is_active">true</data> + <data key="is_active_label">Active</data> + <data key="current_password">{{_ENV.MAGENTO_ADMIN_PASSWORD}}</data> + <data key="role">Administrators</data> + <array key="roles"> + <item>1</item> + </array> + </entity> + <entity name="NewAdminUserWrongCurrentPassword" type="user"> + <data key="username" unique="suffix">admin</data> + <data key="firstname">John</data> + <data key="lastname">Doe</data> + <data key="email" unique="prefix">admin@example.com</data> + <data key="password">123123q</data> + <data key="password_confirmation">123123q</data> + <data key="interface_local">en_US</data> + <data key="interface_local_label">English (United States)</data> + <data key="is_active">true</data> + <data key="is_active_label">Active</data> + <data key="current_password" unique="suffix">password_</data> + <data key="role">Administrators</data> + <array key="roles"> + <item>1</item> + </array> + </entity> <entity name="admin" type="user"> <data key="email">admin@magento.com</data> <data key="password">admin123</data> diff --git a/app/code/Magento/Backend/Test/Mftf/Page/AdminAddNewUserPage.xml b/app/code/Magento/User/Test/Mftf/Page/AdminNewUserPage.xml similarity index 61% rename from app/code/Magento/Backend/Test/Mftf/Page/AdminAddNewUserPage.xml rename to app/code/Magento/User/Test/Mftf/Page/AdminNewUserPage.xml index 4f7dc5539de6f..6de0945793447 100644 --- a/app/code/Magento/Backend/Test/Mftf/Page/AdminAddNewUserPage.xml +++ b/app/code/Magento/User/Test/Mftf/Page/AdminNewUserPage.xml @@ -8,7 +8,8 @@ <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> - <page name="AdminAddNewUserPage" url="admin/user/new" area="admin" module="Backend"> - <section name="AddNewAdminUserSection"/> + <page name="AdminNewUserPage" url="admin/user/new" area="admin" module="Magento_User"> + <section name="AdminNewUserFormSection" /> + <section name="AdminNewUserFormMessagesSection" /> </page> </pages> diff --git a/app/code/Magento/User/Test/Mftf/Section/AdminNewUserFormSection.xml b/app/code/Magento/User/Test/Mftf/Section/AdminNewUserFormSection.xml new file mode 100644 index 0000000000000..9b030b216ce2c --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/Section/AdminNewUserFormSection.xml @@ -0,0 +1,30 @@ +<?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="AdminNewUserFormSection"> + <element name="save" type="button" selector=".page-main-actions #save"/> + + <element name="userInfoTab" type="button" selector="#page_tabs_main_section"/> + <element name="username" type="input" selector="#page_tabs_main_section_content input[name='username']"/> + <element name="firstname" type="input" selector="#page_tabs_main_section_content input[name='firstname']"/> + <element name="lastname" type="input" selector="#page_tabs_main_section_content input[name='lastname']"/> + <element name="email" type="input" selector="#page_tabs_main_section_content input[name='email']"/> + <element name="password" type="input" selector="#page_tabs_main_section_content input[name='password']"/> + <element name="passwordConfirmation" type="input" selector="#page_tabs_main_section_content input[name='password_confirmation']"/> + <element name="interfaceLocale" type="select" selector="#page_tabs_main_section_content select[name='interface_locale']"/> + <element name="currentPassword" type="input" selector="#page_tabs_main_section_content input[name='current_password']"/> + + <element name="userRoleTab" type="button" selector="#page_tabs_roles_section"/> + <element name="search" type="button" selector="#page_tabs_roles_section_content #permissionsUserRolesGrid [data-action='grid-filter-apply']" /> + <element name="resetFilter" type="button" selector="#page_tabs_roles_section_content #permissionsUserRolesGrid [data-action='grid-filter-reset']" /> + <element name="roleFilterField" type="input" selector="#page_tabs_roles_section_content #permissionsUserRolesGrid input[name='role_name']" /> + <element name="roleRadiobutton" type="radio" selector="//table[@id='permissionsUserRolesGrid_table']//tr[./td[contains(@class, 'col-role_name') and contains(., '{{roleName}}')]]//input[@name='roles[]']" parameterized="true"/> + </section> +</sections> diff --git a/app/code/Magento/User/Test/Mftf/Section/AdminUserFormMessagesSection.xml b/app/code/Magento/User/Test/Mftf/Section/AdminUserFormMessagesSection.xml new file mode 100644 index 0000000000000..ec4f4d8bf3ad7 --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/Section/AdminUserFormMessagesSection.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="AdminUserFormMessagesSection"> + <element name="messageByType" type="block" selector="#messages .message-{{messageType}}" parameterized="true" /> + </section> +</sections> From 8a9a986f930cb5f8516b3fe5ecb6d1a6d3f9e8af Mon Sep 17 00:00:00 2001 From: Ruslan Kostiv <rkostiv@adobe.com> Date: Tue, 23 Apr 2019 00:26:38 -0500 Subject: [PATCH 597/603] MC-5681: Onepage Checkout improvements. --- .../BraintreeCreditCardOnCheckoutTest.xml | 2 +- .../Controller/Adminhtml/Product/Search.php | 5 +- .../Block/Checkout/LayoutProcessor.php | 6 + .../Checkout/Model/DefaultConfigProvider.php | 112 ++---------- .../Mftf/ActionGroup/CheckoutActionGroup.xml | 31 ++++ ...FillNewShippingAddressModalActionGroup.xml | 18 ++ ...playBillingAddressOnPaymentPageSection.xml | 14 ++ .../frontend/layout/checkout_index_index.xml | 2 +- .../web/js/action/create-billing-address.js | 13 +- .../web/js/model/checkout-data-resolver.js | 4 +- .../frontend/web/js/view/billing-address.js | 36 ++-- .../web/js/view/billing-address/list.js | 77 ++++++++ .../web/template/billing-address.html | 20 +-- .../web/template/billing-address/actions.html | 21 +++ .../web/template/billing-address/form.html | 2 +- .../view/frontend/web/template/shipping.html | 14 +- .../Address/CustomAttributesProcessor.php | 112 ++++++++++++ .../Address/CustomerAddressDataFormatter.php | 165 ++++++++++++++++++ .../Address/CustomerAddressDataProvider.php | 64 +++++++ .../Test/Mftf/Data/ConfigData.xml | 33 ++++ .../base/web/js/form/element/ui-select.js | 80 ++++++--- app/code/Magento/Wishlist/Helper/Data.php | 8 +- .../Rule/Design/CookieAndSessionMisuse.php | 15 ++ 23 files changed, 672 insertions(+), 182 deletions(-) create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillNewShippingAddressModalActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.xml create mode 100644 app/code/Magento/Checkout/view/frontend/web/js/view/billing-address/list.js create mode 100644 app/code/Magento/Checkout/view/frontend/web/template/billing-address/actions.html create mode 100644 app/code/Magento/Customer/Model/Address/CustomAttributesProcessor.php create mode 100644 app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php create mode 100644 app/code/Magento/Customer/Model/Address/CustomerAddressDataProvider.php create mode 100644 app/code/Magento/OfflinePayments/Test/Mftf/Data/ConfigData.xml diff --git a/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml b/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml index f066c88b12fcc..a781841e0a77b 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml @@ -81,7 +81,7 @@ <actionGroup ref="LoggedInCheckoutFillNewBillingAddressActionGroup" stepKey="LoggedInCheckoutFillNewBillingAddressActionGroup1"> <argument name="Address" value="US_Address_NY"/> </actionGroup> - <click selector="{{CheckoutPaymentSection.addressAction('Save Address')}}" stepKey="SaveAddress"/> + <click selector="{{CheckoutPaymentSection.addressAction('Ship here')}}" stepKey="SaveAddress"/> <waitForPageLoad stepKey="waitForPageLoad9"/> <click selector="{{CheckoutShippingSection.next}}" stepKey="clickNext1"/> <waitForPageLoad stepKey="waitForPageLoad10"/> diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Search.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Search.php index c7c71b2f56026..316983298a1b9 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Search.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Search.php @@ -9,11 +9,12 @@ namespace Magento\Catalog\Controller\Adminhtml\Product; use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Framework\App\Action\HttpGetActionInterface; /** * Controller to search product for ui-select component */ -class Search extends \Magento\Backend\App\Action +class Search extends \Magento\Backend\App\Action implements HttpGetActionInterface { /** * Authorization level of a basic admin session @@ -48,6 +49,8 @@ public function __construct( } /** + * Execute product search. + * * @return \Magento\Framework\Controller\ResultInterface */ public function execute() : \Magento\Framework\Controller\ResultInterface diff --git a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php index 3f6f638db5b82..5d02dd636825b 100644 --- a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php +++ b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php @@ -287,8 +287,14 @@ private function getBillingAddressComponent($paymentCode, $elements) 'provider' => 'checkoutProvider', 'deps' => 'checkoutProvider', 'dataScopePrefix' => 'billingAddress' . $paymentCode, + 'billingAddressListProvider' => '${$.name}.billingAddressList', 'sortOrder' => 1, 'children' => [ + 'billingAddressList' => [ + 'component' => 'Magento_Checkout/js/view/billing-address/list', + 'displayArea' => 'billing-address-list', + 'template' => 'Magento_Checkout/billing-address/list' + ], 'form-fields' => [ 'component' => 'uiComponent', 'displayArea' => 'additional-fieldsets', diff --git a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php index f30bd73deeae2..c2c049d2bf99f 100644 --- a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php +++ b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php @@ -10,6 +10,7 @@ use Magento\Checkout\Model\Session as CheckoutSession; use Magento\Customer\Api\AddressMetadataInterface; use Magento\Customer\Api\CustomerRepositoryInterface as CustomerRepository; +use Magento\Customer\Model\Address\CustomerAddressDataProvider; use Magento\Customer\Model\Context as CustomerContext; use Magento\Customer\Model\Session as CustomerSession; use Magento\Customer\Model\Url as CustomerUrlManager; @@ -177,6 +178,11 @@ class DefaultConfigProvider implements ConfigProviderInterface */ private $addressMetadata; + /** + * @var CustomerAddressDataProvider + */ + private $customerAddressData; + /** * @param CheckoutHelper $checkoutHelper * @param Session $checkoutSession @@ -206,6 +212,7 @@ class DefaultConfigProvider implements ConfigProviderInterface * @param UrlInterface $urlBuilder * @param AddressMetadataInterface $addressMetadata * @param AttributeOptionManagementInterface $attributeOptionManager + * @param CustomerAddressDataProvider|null $customerAddressData * @codeCoverageIgnore * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -237,7 +244,8 @@ public function __construct( \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement, UrlInterface $urlBuilder, AddressMetadataInterface $addressMetadata = null, - AttributeOptionManagementInterface $attributeOptionManager = null + AttributeOptionManagementInterface $attributeOptionManager = null, + CustomerAddressDataProvider $customerAddressData = null ) { $this->checkoutHelper = $checkoutHelper; $this->checkoutSession = $checkoutSession; @@ -268,6 +276,8 @@ public function __construct( $this->addressMetadata = $addressMetadata ?: ObjectManager::getInstance()->get(AddressMetadataInterface::class); $this->attributeOptionManager = $attributeOptionManager ?? ObjectManager::getInstance()->get(AttributeOptionManagementInterface::class); + $this->customerAddressData = $customerAddressData ?: + ObjectManager::getInstance()->get(CustomerAddressDataProvider::class); } /** @@ -359,57 +369,18 @@ private function isAutocompleteEnabled() * * @return array */ - private function getCustomerData() + private function getCustomerData(): array { $customerData = []; if ($this->isCustomerLoggedIn()) { + /** @var \Magento\Customer\Api\Data\CustomerInterface $customer */ $customer = $this->customerRepository->getById($this->customerSession->getCustomerId()); $customerData = $customer->__toArray(); - foreach ($customer->getAddresses() as $key => $address) { - $customerData['addresses'][$key]['inline'] = $this->getCustomerAddressInline($address); - if ($address->getCustomAttributes()) { - $customerData['addresses'][$key]['custom_attributes'] = $this->filterNotVisibleAttributes( - $customerData['addresses'][$key]['custom_attributes'] - ); - } - } + $customerData['addresses'] = $this->customerAddressData->getAddressDataByCustomer($customer); } return $customerData; } - /** - * Filter not visible on storefront custom attributes. - * - * @param array $attributes - * @return array - */ - private function filterNotVisibleAttributes(array $attributes) - { - $attributesMetadata = $this->addressMetadata->getAllAttributesMetadata(); - foreach ($attributesMetadata as $attributeMetadata) { - if (!$attributeMetadata->isVisible()) { - unset($attributes[$attributeMetadata->getAttributeCode()]); - } - } - - return $this->setLabelsToAttributes($attributes); - } - - /** - * Set additional customer address data - * - * @param \Magento\Customer\Api\Data\AddressInterface $address - * @return string - */ - private function getCustomerAddressInline($address) - { - $builtOutputAddressData = $this->addressMapper->toFlatArray($address); - return $this->addressConfig - ->getFormatByCode(\Magento\Customer\Model\Address\Config::DEFAULT_ADDRESS_FORMAT) - ->getRenderer() - ->renderArray($builtOutputAddressData); - } - /** * Retrieve quote data * @@ -726,61 +697,6 @@ private function getPaymentMethods() return $paymentMethods; } - /** - * Set Labels to custom Attributes - * - * @param array $customAttributes - * @return array $customAttributes - * @throws \Magento\Framework\Exception\InputException - * @throws \Magento\Framework\Exception\StateException - */ - private function setLabelsToAttributes(array $customAttributes) : array - { - if (!empty($customAttributes)) { - foreach ($customAttributes as $customAttributeCode => $customAttribute) { - $attributeOptionLabels = $this->getAttributeLabels($customAttribute, $customAttributeCode); - if (!empty($attributeOptionLabels)) { - $customAttributes[$customAttributeCode]['label'] = implode(', ', $attributeOptionLabels); - } - } - } - - return $customAttributes; - } - - /** - * Get Labels by CustomAttribute and CustomAttributeCode - * - * @param array $customAttribute - * @param string|integer $customAttributeCode - * @return array $attributeOptionLabels - * @throws \Magento\Framework\Exception\InputException - * @throws \Magento\Framework\Exception\StateException - */ - private function getAttributeLabels(array $customAttribute, string $customAttributeCode) : array - { - $attributeOptionLabels = []; - - if (!empty($customAttribute['value'])) { - $customAttributeValues = explode(',', $customAttribute['value']); - $attributeOptions = $this->attributeOptionManager->getItems( - \Magento\Customer\Model\Indexer\Address\AttributeProvider::ENTITY, - $customAttributeCode - ); - - if (!empty($attributeOptions)) { - foreach ($attributeOptions as $attributeOption) { - $attributeOptionValue = $attributeOption->getValue(); - if (in_array($attributeOptionValue, $customAttributeValues)) { - $attributeOptionLabels[] = $attributeOption->getLabel() ?? $attributeOptionValue; - } - } - } - } - - return $attributeOptionLabels; - } - /** * Get notification messages for the quote items * diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml index b67b7451d5968..93179a90a7aa1 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml @@ -241,6 +241,21 @@ <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskAfterPaymentMethodSelection"/> </actionGroup> + <!-- Check selected shipping address information on shipping information step --> + <actionGroup name="CheckSelectedShippingAddressInCheckoutActionGroup"> + <arguments> + <argument name="customerVar"/> + <argument name="customerAddressVar"/> + </arguments> + <waitForElement selector="{{CheckoutShippingSection.shippingTab}}" time="30" stepKey="waitForShippingSectionLoaded"/> + <see stepKey="VerifyFirstNameInSelectedAddress" selector="{{CheckoutShippingSection.selectedShippingAddress}}" userInput="{{customerVar.firstname}}" /> + <see stepKey="VerifyLastNameInSelectedAddress" selector="{{CheckoutShippingSection.selectedShippingAddress}}" userInput="{{customerVar.lastname}}" /> + <see stepKey="VerifyStreetInSelectedAddress" selector="{{CheckoutShippingSection.selectedShippingAddress}}" userInput="{{customerAddressVar.street[0]}}" /> + <see stepKey="VerifyCityInSelectedAddress" selector="{{CheckoutShippingSection.selectedShippingAddress}}" userInput="{{customerAddressVar.city}}" /> + <see stepKey="VerifyZipInSelectedAddress" selector="{{CheckoutShippingSection.selectedShippingAddress}}" userInput="{{customerAddressVar.postcode}}" /> + <see stepKey="VerifyPhoneInSelectedAddress" selector="{{CheckoutShippingSection.selectedShippingAddress}}" userInput="{{customerAddressVar.telephone}}" /> + </actionGroup> + <!-- Check billing address in checkout --> <actionGroup name="CheckBillingAddressInCheckoutActionGroup"> <arguments> @@ -257,6 +272,22 @@ <see userInput="{{customerAddressVar.telephone}}" selector="{{CheckoutPaymentSection.billingAddress}}" stepKey="assertBillingAddressTelephone"/> </actionGroup> + <!-- Check billing address in checkout with billing address on payment page --> + <actionGroup name="CheckBillingAddressInCheckoutWithBillingAddressOnPaymentPageActionGroup"> + <arguments> + <argument name="customerVar"/> + <argument name="customerAddressVar"/> + </arguments> + <waitForElement selector="{{CheckoutPaymentSection.paymentSectionTitle}}" time="30" stepKey="waitForPaymentSectionLoaded"/> + <see userInput="{{customerVar.firstName}}" selector="{{CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.billingAddressDetails}}" stepKey="assertBillingAddressDetailsFirstName"/> + <see userInput="{{customerVar.lastName}}" selector="{{CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.billingAddressDetails}}" stepKey="assertBillingAddressDetailsLastName"/> + <see userInput="{{customerAddressVar.street[0]}}" selector="{{CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.billingAddressDetails}}" stepKey="assertBillingAddressDetailsStreet"/> + <see userInput="{{customerAddressVar.city}}" selector="{{CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.billingAddressDetails}}" stepKey="assertBillingAddressDetailsCity"/> + <see userInput="{{customerAddressVar.state}}" selector="{{CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.billingAddressDetails}}" stepKey="assertBillingAddressDetailsState"/> + <see userInput="{{customerAddressVar.postcode}}" selector="{{CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.billingAddressDetails}}" stepKey="assertBillingAddressDetailsPostcode"/> + <see userInput="{{customerAddressVar.telephone}}" selector="{{CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.billingAddressDetails}}" stepKey="assertBillingAddressDetailsTelephone"/> + </actionGroup> + <!-- Checkout place order --> <actionGroup name="CheckoutPlaceOrderActionGroup"> <arguments> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillNewShippingAddressModalActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillNewShippingAddressModalActionGroup.xml new file mode 100644 index 0000000000000..7035855cc0ed3 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillNewShippingAddressModalActionGroup.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="FillNewShippingAddressModalActionGroup" extends="FillShippingAddressOneStreetActionGroup"> + <arguments> + <argument name="address"/> + </arguments> + <selectOption stepKey="selectRegion" selector="{{CheckoutShippingSection.region}}" + userInput="{{address.state}}" after="fillCityName"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.xml new file mode 100644 index 0000000000000..42decd8d43220 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection.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="CheckoutPaymentWithDisplayBillingAddressOnPaymentPageSection"> + <element name="billingAddressDetails" type="text" selector="div.billing-address-details"/> + </section> +</sections> diff --git a/app/code/Magento/Checkout/view/frontend/layout/checkout_index_index.xml b/app/code/Magento/Checkout/view/frontend/layout/checkout_index_index.xml index 64b70e80bd84f..a305413bcf1f3 100644 --- a/app/code/Magento/Checkout/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Magento/Checkout/view/frontend/layout/checkout_index_index.xml @@ -105,7 +105,7 @@ <item name="trigger" xsi:type="string">opc-new-shipping-address</item> <item name="buttons" xsi:type="array"> <item name="save" xsi:type="array"> - <item name="text" xsi:type="string" translate="true">Save Address</item> + <item name="text" xsi:type="string" translate="true">Ship here</item> <item name="class" xsi:type="string">action primary action-save-address</item> </item> <item name="cancel" xsi:type="array"> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/create-billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/action/create-billing-address.js index 7db0dc5ce7473..c601bb8acf125 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/create-billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/create-billing-address.js @@ -12,6 +12,17 @@ define([ 'use strict'; return function (addressData) { - return addressConverter.formAddressDataToQuoteAddress(addressData); + var address = addressConverter.formAddressDataToQuoteAddress(addressData); + + /** + * Returns new customer billing address type. + * + * @returns {String} + */ + address.getType = function () { + return 'new-customer-billing-address'; + }; + + return address; }; }); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js b/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js index e54f464f24d02..bc0ab59b622a2 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js @@ -216,11 +216,11 @@ define([ newCustomerBillingAddressData = checkoutData.getNewCustomerBillingAddress(); if (selectedBillingAddress) { - if (selectedBillingAddress == 'new-customer-address' && newCustomerBillingAddressData) { //eslint-disable-line + if (selectedBillingAddress === 'new-customer-billing-address' && newCustomerBillingAddressData) { selectBillingAddress(createBillingAddress(newCustomerBillingAddressData)); } else { addressList.some(function (address) { - if (selectedBillingAddress == address.getKey()) { //eslint-disable-line eqeqeq + if (selectedBillingAddress === address.getKey()) { selectBillingAddress(address); } }); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js index d68b0682eb511..a552aa01da061 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js @@ -40,30 +40,23 @@ function ( 'use strict'; var lastSelectedBillingAddress = null, - newAddressOption = { - /** - * Get new address label - * @returns {String} - */ - getAddressInline: function () { - return $t('New Address'); - }, - customerAddressId: null - }, countryData = customerData.get('directory-data'), addressOptions = addressList().filter(function (address) { - return address.getType() == 'customer-address'; //eslint-disable-line eqeqeq + return address.getType() === 'customer-address'; }); - addressOptions.push(newAddressOption); - return Component.extend({ defaults: { - template: 'Magento_Checkout/billing-address' + template: 'Magento_Checkout/billing-address', + actionsTemplate: 'Magento_Checkout/billing-address/actions', + formTemplate: 'Magento_Checkout/billing-address/form', + detailsTemplate: 'Magento_Checkout/billing-address/details', + links: { + isAddressFormVisible: '${$.billingAddressListProvider}:isNewAddressSelected' + } }, currentBillingAddress: quote.billingAddress, - addressOptions: addressOptions, - customerHasAddresses: addressOptions.length > 1, + customerHasAddresses: addressOptions.length > 0, /** * Init component @@ -84,7 +77,7 @@ function ( .observe({ selectedAddress: null, isAddressDetailsVisible: quote.billingAddress() != null, - isAddressFormVisible: !customer.isLoggedIn() || addressOptions.length === 1, + isAddressFormVisible: !customer.isLoggedIn() || !addressOptions.length, isAddressSameAsShipping: false, saveInAddressBook: 1 }); @@ -147,7 +140,7 @@ function ( updateAddress: function () { var addressData, newBillingAddress; - if (this.selectedAddress() && this.selectedAddress() != newAddressOption) { //eslint-disable-line eqeqeq + if (this.selectedAddress() && !this.isAddressFormVisible()) { selectBillingAddress(this.selectedAddress()); checkoutData.setSelectedBillingAddress(this.selectedAddress().getKey()); } else { @@ -218,13 +211,6 @@ function ( } }, - /** - * @param {Object} address - */ - onAddressChange: function (address) { - this.isAddressFormVisible(address == newAddressOption); //eslint-disable-line eqeqeq - }, - /** * @param {Number} countryId * @return {*} diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address/list.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address/list.js new file mode 100644 index 0000000000000..ca3a267c01671 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address/list.js @@ -0,0 +1,77 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'uiComponent', + 'Magento_Customer/js/model/address-list', + 'mage/translate', + 'Magento_Customer/js/model/customer' +], function (Component, addressList, $t, customer) { + 'use strict'; + + var newAddressOption = { + /** + * Get new address label + * @returns {String} + */ + getAddressInline: function () { + return $t('New Address'); + }, + customerAddressId: null + }, + addressOptions = addressList().filter(function (address) { + return address.getType() === 'customer-address'; + }); + + return Component.extend({ + defaults: { + template: 'Magento_Checkout/billing-address', + selectedAddress: null, + isNewAddressSelected: false, + addressOptions: addressOptions, + exports: { + selectedAddress: '${ $.parentName }:selectedAddress' + } + }, + + /** + * @returns {Object} Chainable. + */ + initConfig: function () { + this._super(); + this.addressOptions.push(newAddressOption); + + return this; + }, + + /** + * @return {exports.initObservable} + */ + initObservable: function () { + this._super() + .observe('selectedAddress isNewAddressSelected') + .observe({ + isNewAddressSelected: !customer.isLoggedIn() || !addressOptions.length + }); + + return this; + }, + + /** + * @param {Object} address + * @return {*} + */ + addressOptionsText: function (address) { + return address.getAddressInline(); + }, + + /** + * @param {Object} address + */ + onAddressChange: function (address) { + this.isNewAddressSelected(address === newAddressOption); + } + }); +}); diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html index 63edb5057b933..cabfcc9b3db03 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html @@ -5,28 +5,18 @@ */ --> <div class="checkout-billing-address"> - <div class="billing-address-same-as-shipping-block field choice" data-bind="visible: canUseShippingAddress()"> <input type="checkbox" name="billing-address-same-as-shipping" data-bind="checked: isAddressSameAsShipping, click: useShippingAddress, attr: {id: 'billing-address-same-as-shipping-' + getCode($parent)}"/> <label data-bind="attr: {for: 'billing-address-same-as-shipping-' + getCode($parent)}"><span data-bind="i18n: 'My billing and shipping address are the same'"></span></label> </div> - - <!-- ko template: 'Magento_Checkout/billing-address/details' --><!-- /ko --> + <render args="detailsTemplate"/> <fieldset class="fieldset" data-bind="visible: !isAddressDetailsVisible()"> - <!-- ko template: 'Magento_Checkout/billing-address/list' --><!-- /ko --> - <!-- ko template: 'Magento_Checkout/billing-address/form' --><!-- /ko --> - <div class="actions-toolbar"> - <div class="primary"> - <button class="action action-update" type="button" data-bind="click: updateAddress"> - <span data-bind="i18n: 'Update'"></span> - </button> - <button class="action action-cancel" type="button" data-bind="click: cancelAddressEdit, visible: canUseCancelBillingAddress()"> - <span data-bind="i18n: 'Cancel'"></span> - </button> - </div> + <each args="getRegion('billing-address-list')" render="" /> + <div data-bind="fadeVisible: isAddressFormVisible"> + <render args="formTemplate"/> </div> + <render args="actionsTemplate"/> </fieldset> - </div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/actions.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/actions.html new file mode 100644 index 0000000000000..860f340d3f7ca --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/actions.html @@ -0,0 +1,21 @@ +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="actions-toolbar"> + <div class="primary"> + <button class="action action-update" + type="button" + click="updateAddress"> + <span translate="'Update'"/> + </button> + <button class="action action-cancel" + type="button" + click="cancelAddressEdit" + visible="canUseCancelBillingAddress()"> + <span translate="'Cancel'"/> + </button> + </div> +</div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html index 54fe9a1f59394..e29ed99d17be1 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ --> -<div class="billing-address-form" data-bind="fadeVisible: isAddressFormVisible"> +<div class="billing-address-form"> <!-- ko foreach: getRegion('before-fields') --> <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping.html index a1a5aa67a9688..1fcfa4b3b1343 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/shipping.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping.html @@ -16,12 +16,14 @@ <!-- Address form pop up --> <if args="!isFormInline"> - <button type="button" - class="action action-show-popup" - click="showFormPopUp" - visible="!isNewAddressAdded()"> - <span translate="'New Address'" /> - </button> + <div class="new-address-popup"> + <button type="button" + class="action action-show-popup" + click="showFormPopUp" + visible="!isNewAddressAdded()"> + <span translate="'New Address'" /> + </button> + </div> <div id="opc-new-shipping-address" visible="isFormPopUpVisible()" render="shippingFormTemplate" /> diff --git a/app/code/Magento/Customer/Model/Address/CustomAttributesProcessor.php b/app/code/Magento/Customer/Model/Address/CustomAttributesProcessor.php new file mode 100644 index 0000000000000..d6e63e11ee453 --- /dev/null +++ b/app/code/Magento/Customer/Model/Address/CustomAttributesProcessor.php @@ -0,0 +1,112 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\Address; + +use Magento\Customer\Api\AddressMetadataInterface; +use Magento\Eav\Api\AttributeOptionManagementInterface; + +/** + * Provides customer address data. + */ +class CustomAttributesProcessor +{ + /** + * @var AddressMetadataInterface + */ + private $addressMetadata; + + /** + * @var AttributeOptionManagementInterface + */ + private $attributeOptionManager; + + /** + * @param AddressMetadataInterface $addressMetadata + * @param AttributeOptionManagementInterface $attributeOptionManager + */ + public function __construct( + AddressMetadataInterface $addressMetadata, + AttributeOptionManagementInterface $attributeOptionManager + ) { + $this->addressMetadata = $addressMetadata; + $this->attributeOptionManager = $attributeOptionManager; + } + + /** + * Set Labels to custom Attributes + * + * @param \Magento\Framework\Api\AttributeValue[] $customAttributes + * @return array $customAttributes + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\StateException + */ + private function setLabelsForAttributes(array $customAttributes): array + { + if (!empty($customAttributes)) { + foreach ($customAttributes as $customAttributeCode => $customAttribute) { + $attributeOptionLabels = $this->getAttributeLabels($customAttribute, $customAttributeCode); + if (!empty($attributeOptionLabels)) { + $customAttributes[$customAttributeCode]['label'] = implode(', ', $attributeOptionLabels); + } + } + } + + return $customAttributes; + } + /** + * Get Labels by CustomAttribute and CustomAttributeCode + * + * @param array $customAttribute + * @param string $customAttributeCode + * @return array $attributeOptionLabels + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\StateException + */ + private function getAttributeLabels(array $customAttribute, string $customAttributeCode) : array + { + $attributeOptionLabels = []; + + if (!empty($customAttribute['value'])) { + $customAttributeValues = explode(',', $customAttribute['value']); + $attributeOptions = $this->attributeOptionManager->getItems( + \Magento\Customer\Model\Indexer\Address\AttributeProvider::ENTITY, + $customAttributeCode + ); + + if (!empty($attributeOptions)) { + foreach ($attributeOptions as $attributeOption) { + $attributeOptionValue = $attributeOption->getValue(); + if (\in_array($attributeOptionValue, $customAttributeValues, false)) { + $attributeOptionLabels[] = $attributeOption->getLabel() ?? $attributeOptionValue; + } + } + } + } + + return $attributeOptionLabels; + } + + /** + * Filter not visible on storefront custom attributes. + * + * @param array $attributes + * @return array + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function filterNotVisibleAttributes(array $attributes): array + { + $attributesMetadata = $this->addressMetadata->getAllAttributesMetadata(); + foreach ($attributesMetadata as $attributeMetadata) { + if (!$attributeMetadata->isVisible()) { + unset($attributes[$attributeMetadata->getAttributeCode()]); + } + } + + return $this->setLabelsForAttributes($attributes); + } +} diff --git a/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php new file mode 100644 index 0000000000000..e80cc0d69e91d --- /dev/null +++ b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php @@ -0,0 +1,165 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\Address; + +use Magento\Customer\Api\Data\AddressInterface; +use Magento\Customer\Model\Address\Mapper as AddressMapper; +use Magento\Customer\Model\Address\Config as AddressConfig; + +/** + * Provides method to format customer address data. + */ +class CustomerAddressDataFormatter +{ + /** + * @var AddressMapper + */ + private $addressMapper; + + /** + * @var AddressConfig + */ + private $addressConfig; + + /** + * @var CustomAttributesProcessor + */ + private $customAttributesProcessor; + + /** + * @param Mapper $addressMapper + * @param Config $addressConfig + * @param CustomAttributesProcessor $customAttributesProcessor + */ + public function __construct( + AddressMapper $addressMapper, + AddressConfig $addressConfig, + CustomAttributesProcessor $customAttributesProcessor + ) { + $this->addressMapper = $addressMapper; + $this->addressConfig = $addressConfig; + $this->customAttributesProcessor = $customAttributesProcessor; + } + + /** + * Prepare list of addressed that was selected by customer on checkout page. + * + * @param \Magento\Customer\Api\Data\CustomerInterface $customer + * @param \Magento\Quote\Model\Quote $quote + * @param array $prepareAddressList + * @return array + */ + public function prepareSelectedAddresses( + \Magento\Customer\Api\Data\CustomerInterface $customer, + \Magento\Quote\Model\Quote $quote, + array $prepareAddressList + ): array { + /** @var AddressInterface $billingAddress */ + $billingAddress = $quote->getBillingAddress(); + $billingAddressId = $billingAddress->getOrigData('customer_address_id'); + $prepareAddressList = $this->prepareSelectedAddress($customer, $prepareAddressList, $billingAddressId); + + $shippingAddressId = null; + $shippingAssignments = $quote->getExtensionAttributes()->getShippingAssignments(); + if (isset($shippingAssignments[0])) { + $shipping = current($shippingAssignments)->getData('shipping'); + /** @var AddressInterface $shippingAddress */ + $shippingAddress = $shipping->getAddress(); + $shippingAddressId = $shippingAddress->getOrigData('customer_address_id'); + } + + $prepareAddressList = $this->prepareSelectedAddress($customer, $prepareAddressList, $shippingAddressId); + + return $prepareAddressList; + } + + /** + * Prepare customer address data. + * + * @param AddressInterface $customerAddress + * @return array + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function prepareAddress(AddressInterface $customerAddress) + { + $resultAddress = [ + 'id' => $customerAddress->getId(), + 'customer_id' => $customerAddress->getCustomerId(), + 'company' => $customerAddress->getCompany(), + 'prefix' => $customerAddress->getPrefix(), + 'firstname' => $customerAddress->getFirstname(), + 'lastname' => $customerAddress->getLastname(), + 'middlename' => $customerAddress->getMiddlename(), + 'suffix' => $customerAddress->getSuffix(), + 'street' => $customerAddress->getStreet(), + 'city' => $customerAddress->getCity(), + 'region' => [ + 'region' => $customerAddress->getRegion()->getRegion(), + 'region_code' => $customerAddress->getRegion()->getRegionCode(), + 'region_id' => $customerAddress->getRegion()->getRegionId(), + ], + 'region_id' => $customerAddress->getRegionId(), + 'postcode' => $customerAddress->getPostcode(), + 'country_id' => $customerAddress->getCountryId(), + 'telephone' => $customerAddress->getTelephone(), + 'fax' => $customerAddress->getFax(), + 'default_billing' => $customerAddress->isDefaultBilling(), + 'default_shipping' => $customerAddress->isDefaultShipping(), + 'inline' => $this->getCustomerAddressInline($customerAddress), + 'custom_attributes' => [], + 'extension_attributes' => $customerAddress->getExtensionAttributes(), + ]; + + if ($customerAddress->getCustomAttributes()) { + $customerAddress = $customerAddress->__toArray(); + $resultAddress['custom_attributes'] = $this->customAttributesProcessor->filterNotVisibleAttributes( + $customerAddress['custom_attributes'] + ); + } + + return $resultAddress; + } + + /** + * Prepared address by for given customer with given address id. + * + * @param \Magento\Customer\Api\Data\CustomerInterface $customer + * @param array $addressList + * @param int|null $addressId + * @return array + */ + private function prepareSelectedAddress( + \Magento\Customer\Api\Data\CustomerInterface $customer, + array $addressList, + $addressId = null + ): array { + if (null !== $addressId && !isset($addressList[$addressId])) { + $selectedAddress = $this->prepareAddress($customer->getAddresses()[$addressId]); + if (isset($selectedAddress['id'])) { + $addressList[$selectedAddress['id']] = $selectedAddress; + } + } + + return $addressList; + } + + /** + * Set additional customer address data + * + * @param AddressInterface $address + * @return string + */ + private function getCustomerAddressInline(AddressInterface $address): string + { + $builtOutputAddressData = $this->addressMapper->toFlatArray($address); + return $this->addressConfig + ->getFormatByCode(AddressConfig::DEFAULT_ADDRESS_FORMAT) + ->getRenderer() + ->renderArray($builtOutputAddressData); + } +} diff --git a/app/code/Magento/Customer/Model/Address/CustomerAddressDataProvider.php b/app/code/Magento/Customer/Model/Address/CustomerAddressDataProvider.php new file mode 100644 index 0000000000000..04fdd2a7f7266 --- /dev/null +++ b/app/code/Magento/Customer/Model/Address/CustomerAddressDataProvider.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\Address; + +/** + * Provides customer address data. + */ +class CustomerAddressDataProvider +{ + /** + * Customer addresses. + * + * @var array + */ + private $customerAddresses = []; + + /** + * @var CustomerAddressDataFormatter + */ + private $customerAddressDataFormatter; + + /** + * @param CustomerAddressDataFormatter $customerAddressDataFormatter + */ + public function __construct( + CustomerAddressDataFormatter $customerAddressDataFormatter + ) { + $this->customerAddressDataFormatter = $customerAddressDataFormatter; + } + + /** + * Get addresses for customer. + * + * @param \Magento\Customer\Api\Data\CustomerInterface $customer + * @return array + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function getAddressDataByCustomer( + \Magento\Customer\Api\Data\CustomerInterface $customer + ): array { + if (!empty($this->customerAddresses)) { + return $this->customerAddresses; + } + + $customerOriginAddresses = $customer->getAddresses(); + if (!$customerOriginAddresses) { + return []; + } + + $customerAddresses = []; + foreach ($customerOriginAddresses as $address) { + $customerAddresses[$address->getId()] = $this->customerAddressDataFormatter->prepareAddress($address); + } + + $this->customerAddresses = $customerAddresses; + + return $this->customerAddresses; + } +} diff --git a/app/code/Magento/OfflinePayments/Test/Mftf/Data/ConfigData.xml b/app/code/Magento/OfflinePayments/Test/Mftf/Data/ConfigData.xml new file mode 100644 index 0000000000000..ec8dd46a00d8e --- /dev/null +++ b/app/code/Magento/OfflinePayments/Test/Mftf/Data/ConfigData.xml @@ -0,0 +1,33 @@ +<?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="DisableCheckMoneyOrderPaymentMethod"> + <data key="path">payment/checkmo/active</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="EnableCheckMoneyOrderPaymentMethod"> + <!-- Magento default value --> + <data key="path">payment/checkmo/active</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="DisableCashOnDeliveryPaymentMethod"> + <!-- Magento default value --> + <data key="path">payment/cashondelivery/active</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="EnableCashOnDeliveryPaymentMethod"> + <data key="path">payment/cashondelivery/active</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> +</entities> diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js b/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js index dba0992c5ba52..4479cff5135dc 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js @@ -131,6 +131,7 @@ define([ return Abstract.extend({ defaults: { options: [], + total: 0, listVisible: false, value: [], filterOptions: false, @@ -153,6 +154,7 @@ define([ labelsDecoration: false, disableLabel: false, filterRateLimit: 500, + filterRateLimitMethod: 'notifyAtFixedRate', closeBtnLabel: $t('Done'), optgroupTmpl: 'ui/grid/filters/elements/ui-select-optgroup', quantityPlaceholder: $t('options'), @@ -180,6 +182,7 @@ define([ debounce: 300, missingValuePlaceholder: $t('Entity with ID: %s doesn\'t exist'), isDisplayMissingValuePlaceholder: false, + currentSearchKey: '', listens: { listVisible: 'cleanHoveredElement', filterInputValue: 'filterOptionsList', @@ -330,7 +333,10 @@ define([ ]); this.filterInputValue.extend({ - rateLimit: this.filterRateLimit + rateLimit: { + timeout: this.filterRateLimit, + method: this.filterRateLimitMethod + } }); return this; @@ -460,7 +466,7 @@ define([ } if (this.searchOptions) { - return _.debounce(this.loadOptions.bind(this, value), this.debounce)(); + return this.loadOptions(value); } this.cleanHoveredElement(); @@ -547,11 +553,21 @@ define([ _setItemsQuantity: function (data) { if (this.showFilteredQuantity) { data || parseInt(data, 10) === 0 ? - this.itemsQuantity(data + ' ' + this.quantityPlaceholder) : + this.itemsQuantity(this.getItemsPlaceholder(data)) : this.itemsQuantity(''); } }, + /** + * Return formatted items placeholder. + * + * @param {Object} data - option data + * @returns {String} + */ + getItemsPlaceholder: function (data) { + return data + ' ' + this.quantityPlaceholder; + }, + /** * Remove element from selected array */ @@ -1234,13 +1250,11 @@ define([ * @param {Number} page */ processRequest: function (searchKey, page) { - var total = 0, - existingOptions = this.options(); - this.loading(true); + this.currentSearchKey = searchKey; $.ajax({ url: this.searchUrl, - type: 'post', + type: 'get', dataType: 'json', context: this, data: { @@ -1248,27 +1262,39 @@ define([ page: page, limit: this.pageLimit }, + success: $.proxy(this.success, this), + error: $.proxy(this.error, this), + beforeSend: $.proxy(this.beforeSend, this), + complete: $.proxy(this.complete, this, searchKey, page) + }); + }, - /** @param {Object} response */ - success: function (response) { - _.each(response.options, function (opt) { - existingOptions.push(opt); - }); - total = response.total; - this.options(existingOptions); - }, - - /** set empty array if error occurs */ - error: function () { - this.options([]); - }, + /** @param {Object} response */ + success: function (response) { + var existingOptions = this.options(); - /** cache options and stop loading*/ - complete: function () { - this.setCachedSearchResults(searchKey, this.options(), page, total); - this.afterLoadOptions(searchKey, page, total); - } + _.each(response.options, function (opt) { + existingOptions.push(opt); }); + + this.total = response.total; + this.options(existingOptions); + }, + + /** add actions before ajax request */ + beforeSend: function () { + + }, + + /** set empty array if error occurs */ + error: function () { + this.options([]); + }, + + /** cache options and stop loading*/ + complete: function (searchKey, page) { + this.setCachedSearchResults(searchKey, this.options(), page, this.total); + this.afterLoadOptions(searchKey, page, this.total); }, /** @@ -1279,9 +1305,9 @@ define([ * @param {Number} total */ afterLoadOptions: function (searchKey, page, total) { - this._setItemsQuantity(total); - this.lastSearchPage = page; this.lastSearchKey = searchKey; + this.lastSearchPage = page; + this._setItemsQuantity(total); this.loading(false); } }); diff --git a/app/code/Magento/Wishlist/Helper/Data.php b/app/code/Magento/Wishlist/Helper/Data.php index 3b9f431566da0..0589747a52d33 100644 --- a/app/code/Magento/Wishlist/Helper/Data.php +++ b/app/code/Magento/Wishlist/Helper/Data.php @@ -171,7 +171,7 @@ public function setCustomer(\Magento\Customer\Api\Data\CustomerInterface $custom public function getCustomer() { if (!$this->_currentCustomer && $this->_customerSession->isLoggedIn()) { - $this->_currentCustomer = $this->_customerSession->getCustomerDataObject(); + $this->_currentCustomer = $this->_customerSession->getCustomerData(); } return $this->_currentCustomer; } @@ -355,7 +355,7 @@ public function getMoveFromCartParams($itemId) * * @param \Magento\Catalog\Model\Product|\Magento\Wishlist\Model\Item $item * - * @return string|false + * @return string|false */ public function getUpdateParams($item) { @@ -382,7 +382,7 @@ public function getUpdateParams($item) * Retrieve params for adding item to shopping cart * * @param string|\Magento\Catalog\Model\Product|\Magento\Wishlist\Model\Item $item - * @return string + * @return string */ public function getAddToCartUrl($item) { @@ -428,7 +428,7 @@ public function addRefererToParams(array $params) * Retrieve URL for adding item to shopping cart from shared wishlist * * @param string|\Magento\Catalog\Model\Product|\Magento\Wishlist\Model\Item $item - * @return string + * @return string */ public function getSharedAddToCartUrl($item) { diff --git a/dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/CookieAndSessionMisuse.php b/dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/CookieAndSessionMisuse.php index ee56158a54509..707c3442d4056 100644 --- a/dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/CookieAndSessionMisuse.php +++ b/dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/CookieAndSessionMisuse.php @@ -54,6 +54,19 @@ private function isUiDataProvider(\ReflectionClass $class): bool ); } + /** + * Is given class a Layout Processor? + * + * @param \ReflectionClass $class + * @return bool + */ + private function isLayoutProcessor(\ReflectionClass $class): bool + { + return $class->isSubclassOf( + \Magento\Checkout\Block\Checkout\LayoutProcessorInterface::class + ); + } + /** * Is given class an HTML UI Document? * @@ -159,6 +172,7 @@ private function doesUseRestrictedClasses(\ReflectionClass $class): bool * @inheritdoc * * @param ClassNode|ASTClass $node + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function apply(AbstractNode $node) { @@ -176,6 +190,7 @@ public function apply(AbstractNode $node) && !$this->isUiDocument($class) && !$this->isControllerPlugin($class) && !$this->isBlockPlugin($class) + && !$this->isLayoutProcessor($class) ) { $this->addViolation($node, [$node->getFullQualifiedName()]); } From 8d78cc194382fe04827b26ffe8fb760878e54ee2 Mon Sep 17 00:00:00 2001 From: Ruslan Kostiv <rkostiv@adobe.com> Date: Tue, 23 Apr 2019 11:08:43 -0500 Subject: [PATCH 598/603] MC-5681: Onepage Checkout improvements. --- app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php | 1 + app/code/Magento/Checkout/Model/DefaultConfigProvider.php | 1 + app/code/Magento/Wishlist/Helper/Data.php | 1 + 3 files changed, 3 insertions(+) diff --git a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php index 5d02dd636825b..557f143352446 100644 --- a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php +++ b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php @@ -122,6 +122,7 @@ private function convertElementsToSelect($elements, $attributesToConvert) if (!in_array($code, $codes)) { continue; } + // phpcs:ignore Magento2.Functions.DiscouragedFunction $options = call_user_func($attributesToConvert[$code]); if (!is_array($options)) { continue; diff --git a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php index c2c049d2bf99f..470d4a3aca561 100644 --- a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php +++ b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php @@ -35,6 +35,7 @@ * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class DefaultConfigProvider implements ConfigProviderInterface { diff --git a/app/code/Magento/Wishlist/Helper/Data.php b/app/code/Magento/Wishlist/Helper/Data.php index 0589747a52d33..3d25e16294fcd 100644 --- a/app/code/Magento/Wishlist/Helper/Data.php +++ b/app/code/Magento/Wishlist/Helper/Data.php @@ -13,6 +13,7 @@ * * @author Magento Core Team <core@magentocommerce.com> * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * * @api * @since 100.0.2 From c26f2ac57f771f67ed2ff40dbe5e6e52236d0e55 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@magento.com> Date: Tue, 23 Apr 2019 13:18:04 -0500 Subject: [PATCH 599/603] magento-engcom/magento2ce#2781: Fixed code style issues --- .../Model/Entity/Attribute/Source/AbstractSource.php | 2 +- .../Downloadable/Api/ProductRepositoryTest.php | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php index a81d437acea36..dd4cd4217a127 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php @@ -8,7 +8,7 @@ /** * Entity/Attribute/Model - attribute selection source abstract - * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @author Magento Core Team <core@magentocommerce.com> * @SuppressWarnings(PHPMD.NumberOfChildren) diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php index d0cace993a24a..769abadf20585 100644 --- a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php @@ -51,11 +51,13 @@ protected function getLinkData() 'link_type' => 'file', 'link_file_content' => [ 'name' => 'link1_content.jpg', + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], 'sample_type' => 'file', 'sample_file_content' => [ 'name' => 'link1_sample.jpg', + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], ], @@ -114,6 +116,7 @@ protected function getSampleData() 'sample_type' => 'file', 'sample_file_content' => [ 'name' => 'sample2.jpg', + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], ], @@ -146,7 +149,9 @@ protected function createDownloadableProduct() "price" => 10, 'attribute_set_id' => 4, "extension_attributes" => [ + // phpcs:ignore Magento2.Functions.DiscouragedFunction "downloadable_product_links" => array_values($this->getLinkData()), + // phpcs:ignore Magento2.Functions.DiscouragedFunction "downloadable_product_samples" => array_values($this->getSampleData()), ], ]; @@ -301,11 +306,13 @@ public function testUpdateDownloadableProductLinksWithNewFile() 'link_type' => 'file', 'link_file_content' => [ 'name' => $linkFile . $extension, + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], 'sample_type' => 'file', 'sample_file_content' => [ 'name' => $sampleFile . $extension, + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], ]; @@ -319,11 +326,13 @@ public function testUpdateDownloadableProductLinksWithNewFile() 'link_type' => 'file', 'link_file_content' => [ 'name' => 'link2_content.jpg', + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], 'sample_type' => 'file', 'sample_file_content' => [ 'name' => 'link2_sample.jpg', + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], ]; @@ -463,6 +472,7 @@ public function testUpdateDownloadableProductSamplesWithNewFile() 'sample_type' => 'file', 'sample_file_content' => [ 'name' => 'sample1.jpg', + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], ]; @@ -474,6 +484,7 @@ public function testUpdateDownloadableProductSamplesWithNewFile() 'sample_type' => 'file', 'sample_file_content' => [ 'name' => 'sample2.jpg', + // phpcs:ignore Magento2.Functions.DiscouragedFunction 'file_data' => base64_encode(file_get_contents($this->testImagePath)), ], ]; From 461b661ee8d491e5f88a5893e664857bec2fb7d4 Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy <dpoperechnyy@magento.com> Date: Tue, 23 Apr 2019 14:05:29 -0500 Subject: [PATCH 600/603] MC-5681: Onepage Checkout improvements - Fix fatal with no default billing or shipping address; --- .../Model/Address/CustomerAddressDataFormatter.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php index e80cc0d69e91d..a95fe3e128470 100644 --- a/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php +++ b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php @@ -139,9 +139,17 @@ private function prepareSelectedAddress( $addressId = null ): array { if (null !== $addressId && !isset($addressList[$addressId])) { - $selectedAddress = $this->prepareAddress($customer->getAddresses()[$addressId]); - if (isset($selectedAddress['id'])) { - $addressList[$selectedAddress['id']] = $selectedAddress; + $filteredDefaultAddress = array_filter( + $customer->getAddresses(), + function ($address) use ($addressId) { + return $address->getId() === $addressId; + } + ); + if (!empty ($filteredDefaultAddress)) { + $selectedAddress = $this->prepareAddress(current($filteredDefaultAddress)); + if (isset($selectedAddress['id'])) { + $addressList[$selectedAddress['id']] = $selectedAddress; + } } } From 666e8c3e2c14a917415c0e09c4c998dafa383bb9 Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy <dpoperechnyy@magento.com> Date: Tue, 23 Apr 2019 14:07:55 -0500 Subject: [PATCH 601/603] MC-5681: Onepage Checkout improvements - Rename variable; --- .../Customer/Model/Address/CustomerAddressDataFormatter.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php index a95fe3e128470..85492bbb2de65 100644 --- a/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php +++ b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php @@ -139,14 +139,14 @@ private function prepareSelectedAddress( $addressId = null ): array { if (null !== $addressId && !isset($addressList[$addressId])) { - $filteredDefaultAddress = array_filter( + $filteredAddress = array_filter( $customer->getAddresses(), function ($address) use ($addressId) { return $address->getId() === $addressId; } ); - if (!empty ($filteredDefaultAddress)) { - $selectedAddress = $this->prepareAddress(current($filteredDefaultAddress)); + if (!empty ($filteredAddress)) { + $selectedAddress = $this->prepareAddress(current($filteredAddress)); if (isset($selectedAddress['id'])) { $addressList[$selectedAddress['id']] = $selectedAddress; } From a44f50ae67a1c0a26e8bd2bf8b8c881c18566503 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@magento.com> Date: Tue, 23 Apr 2019 14:31:53 -0500 Subject: [PATCH 602/603] magento-engcom/magento2ce#2781: Fixed integration test (Travis failures) --- .../Model/Import/ProductTest.php | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index 70c16e05712b9..67446960e15dc 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -1595,7 +1595,6 @@ public function testAddUpdateProductWithInvalidUrlKeys() : void /** * Make sure the non existing image in the csv file won't erase the qty key of the existing products. * - * @magentoDataFixture Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_non_existing_image.csv * @magentoDbIsolation enabled * @magentoAppIsolation enabled */ @@ -1604,24 +1603,8 @@ public function testImportWithNonExistingImage() $products = [ 'simple_new' => 100, ]; - $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_non_existing_image.csv', - 'directory' => $directory - ] - ); - $errors = $this->_model->setParameters( - ['behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, 'entity' => 'catalog_product'] - ) - ->setSource($source) - ->validateData(); - - $this->assertTrue($errors->getErrorsCount() == 0); - $this->_model->importData(); + $this->importFile('products_to_import_with_non_existing_image.csv'); $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); foreach ($products as $productSku => $productQty) { From c40251a7588695b7c675f4e05dec8fb72718b773 Mon Sep 17 00:00:00 2001 From: Ruslan Kostiv <rkostiv@adobe.com> Date: Tue, 23 Apr 2019 14:44:05 -0500 Subject: [PATCH 603/603] MC-5681: Onepage Checkout improvements. --- .../Address/CustomerAddressDataFormatter.php | 55 ------------------- 1 file changed, 55 deletions(-) diff --git a/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php index e80cc0d69e91d..9202d7492040c 100644 --- a/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php +++ b/app/code/Magento/Customer/Model/Address/CustomerAddressDataFormatter.php @@ -46,38 +46,6 @@ public function __construct( $this->customAttributesProcessor = $customAttributesProcessor; } - /** - * Prepare list of addressed that was selected by customer on checkout page. - * - * @param \Magento\Customer\Api\Data\CustomerInterface $customer - * @param \Magento\Quote\Model\Quote $quote - * @param array $prepareAddressList - * @return array - */ - public function prepareSelectedAddresses( - \Magento\Customer\Api\Data\CustomerInterface $customer, - \Magento\Quote\Model\Quote $quote, - array $prepareAddressList - ): array { - /** @var AddressInterface $billingAddress */ - $billingAddress = $quote->getBillingAddress(); - $billingAddressId = $billingAddress->getOrigData('customer_address_id'); - $prepareAddressList = $this->prepareSelectedAddress($customer, $prepareAddressList, $billingAddressId); - - $shippingAddressId = null; - $shippingAssignments = $quote->getExtensionAttributes()->getShippingAssignments(); - if (isset($shippingAssignments[0])) { - $shipping = current($shippingAssignments)->getData('shipping'); - /** @var AddressInterface $shippingAddress */ - $shippingAddress = $shipping->getAddress(); - $shippingAddressId = $shippingAddress->getOrigData('customer_address_id'); - } - - $prepareAddressList = $this->prepareSelectedAddress($customer, $prepareAddressList, $shippingAddressId); - - return $prepareAddressList; - } - /** * Prepare customer address data. * @@ -125,29 +93,6 @@ public function prepareAddress(AddressInterface $customerAddress) return $resultAddress; } - /** - * Prepared address by for given customer with given address id. - * - * @param \Magento\Customer\Api\Data\CustomerInterface $customer - * @param array $addressList - * @param int|null $addressId - * @return array - */ - private function prepareSelectedAddress( - \Magento\Customer\Api\Data\CustomerInterface $customer, - array $addressList, - $addressId = null - ): array { - if (null !== $addressId && !isset($addressList[$addressId])) { - $selectedAddress = $this->prepareAddress($customer->getAddresses()[$addressId]); - if (isset($selectedAddress['id'])) { - $addressList[$selectedAddress['id']] = $selectedAddress; - } - } - - return $addressList; - } - /** * Set additional customer address data *