From 34fdfec0938b2305a3164f3360e931d3486d6515 Mon Sep 17 00:00:00 2001 From: francesco Date: Thu, 4 Oct 2018 16:41:35 +0200 Subject: [PATCH 001/142] Fix phpdocumentor - inheritdoc imports long description only --- app/code/Magento/Customer/Model/Address.php | 20 ++++++++- app/code/Magento/Customer/Model/Customer.php | 6 +++ .../ResourceModel/CustomerRepository.php | 43 ++++++++++++++++--- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Customer/Model/Address.php b/app/code/Magento/Customer/Model/Address.php index 1dcd8516af69f..376390011056d 100644 --- a/app/code/Magento/Customer/Model/Address.php +++ b/app/code/Magento/Customer/Model/Address.php @@ -122,6 +122,8 @@ public function __construct( } /** + * Initialize address model + * * @return void */ protected function _construct() @@ -168,7 +170,14 @@ public function updateData(AddressInterface $address) } /** - * {@inheritdoc} + * Create address data object based on current address model. + * + * @param int|null $defaultBillingAddressId + * @param int|null $defaultShippingAddressId + * @return AddressInterface + * Use Api/Data/AddressInterface as a result of service operations. Don't rely on the model to provide + * the instance of Api/Data/AddressInterface + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function getDataModel($defaultBillingAddressId = null, $defaultShippingAddressId = null) { @@ -261,6 +270,8 @@ public function getDefaultAttributeCodes() } /** + * Clone address + * * @return void */ public function __clone() @@ -301,6 +312,8 @@ public function setRegionId($regionId) } /** + * Create Customer from Factory + * * @return Customer */ protected function _createCustomer() @@ -356,7 +369,11 @@ public function reindex() } /** + * Get a list of custom attribute codes. + * * {@inheritdoc} + * + * @return string[] * @since 100.0.6 */ protected function getCustomAttributesCodes() @@ -366,6 +383,7 @@ protected function getCustomAttributesCodes() /** * Get new AttributeList dependency for application code. + * * @return \Magento\Customer\Model\Address\CustomAttributeListInterface * @deprecated 100.0.6 */ diff --git a/app/code/Magento/Customer/Model/Customer.php b/app/code/Magento/Customer/Model/Customer.php index 6d1c1549216e8..a1a64cb7e4078 100644 --- a/app/code/Magento/Customer/Model/Customer.php +++ b/app/code/Magento/Customer/Model/Customer.php @@ -1292,6 +1292,8 @@ public function getResetPasswordLinkExpirationPeriod() } /** + * Create Address from Factory + * * @return Address */ protected function _createAddressInstance() @@ -1300,6 +1302,8 @@ protected function _createAddressInstance() } /** + * Create Address Collection from Factory + * * @return \Magento\Customer\Model\ResourceModel\Address\Collection */ protected function _createAddressCollection() @@ -1308,6 +1312,8 @@ protected function _createAddressCollection() } /** + * Get Template Types + * * @return array */ protected function getTemplateTypes() diff --git a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php index 29e35c721a3be..b5696d5b19ee5 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php +++ b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php @@ -161,7 +161,14 @@ public function __construct( } /** - * {@inheritdoc} + * Create or update a customer. + * + * @param \Magento\Customer\Api\Data\CustomerInterface $customer + * @param string $passwordHash + * @return \Magento\Customer\Api\Data\CustomerInterface + * @throws \Magento\Framework\Exception\InputException If bad input is provided + * @throws \Magento\Framework\Exception\State\InputMismatchException If the provided email is already used + * @throws \Magento\Framework\Exception\LocalizedException * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ @@ -293,7 +300,13 @@ private function populateCustomerWithSecureData($customerModel, $passwordHash = } /** - * {@inheritdoc} + * Retrieve customer. + * + * @param string $email + * @param int|null $websiteId + * @return \Magento\Customer\Api\Data\CustomerInterface + * @throws \Magento\Framework\Exception\NoSuchEntityException If customer with the specified email does not exist. + * @throws \Magento\Framework\Exception\LocalizedException */ public function get($email, $websiteId = null) { @@ -302,7 +315,12 @@ public function get($email, $websiteId = null) } /** - * {@inheritdoc} + * Get customer by Customer ID. + * + * @param int $customerId + * @return \Magento\Customer\Api\Data\CustomerInterface + * @throws \Magento\Framework\Exception\NoSuchEntityException If customer with the specified ID does not exist. + * @throws \Magento\Framework\Exception\LocalizedException */ public function getById($customerId) { @@ -311,7 +329,13 @@ public function getById($customerId) } /** + * Retrieve customers which match a specified criteria. + * * {@inheritdoc} + * + * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria + * @return \Magento\Customer\Api\Data\CustomerSearchResultsInterface + * @throws \Magento\Framework\Exception\LocalizedException */ public function getList(SearchCriteriaInterface $searchCriteria) { @@ -351,7 +375,11 @@ public function getList(SearchCriteriaInterface $searchCriteria) } /** - * {@inheritdoc} + * Delete customer. + * + * @param \Magento\Customer\Api\Data\CustomerInterface $customer + * @return bool true on success + * @throws \Magento\Framework\Exception\LocalizedException */ public function delete(CustomerInterface $customer) { @@ -359,7 +387,12 @@ public function delete(CustomerInterface $customer) } /** - * {@inheritdoc} + * Delete customer by Customer ID. + * + * @param int $customerId + * @return bool true on success + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\LocalizedException */ public function deleteById($customerId) { From 05e02c223d57fc6cfe669e84bff78cb2984460ce Mon Sep 17 00:00:00 2001 From: francesco Date: Fri, 5 Oct 2018 08:29:17 +0200 Subject: [PATCH 002/142] Fix phpdocumentor - automatic inherit if doc is without changes --- app/code/Magento/Customer/Model/Address.php | 12 +----- .../ResourceModel/CustomerRepository.php | 41 ------------------- 2 files changed, 1 insertion(+), 52 deletions(-) diff --git a/app/code/Magento/Customer/Model/Address.php b/app/code/Magento/Customer/Model/Address.php index 376390011056d..1206f157c7fc5 100644 --- a/app/code/Magento/Customer/Model/Address.php +++ b/app/code/Magento/Customer/Model/Address.php @@ -169,16 +169,6 @@ public function updateData(AddressInterface $address) return $this; } - /** - * Create address data object based on current address model. - * - * @param int|null $defaultBillingAddressId - * @param int|null $defaultShippingAddressId - * @return AddressInterface - * Use Api/Data/AddressInterface as a result of service operations. Don't rely on the model to provide - * the instance of Api/Data/AddressInterface - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ public function getDataModel($defaultBillingAddressId = null, $defaultShippingAddressId = null) { if ($this->getCustomerId() || $this->getParentId()) { @@ -371,7 +361,7 @@ public function reindex() /** * Get a list of custom attribute codes. * - * {@inheritdoc} + * By default, entity can be extended only using extension attributes functionality. * * @return string[] * @since 100.0.6 diff --git a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php index b5696d5b19ee5..e90aa5e319c65 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php +++ b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php @@ -299,44 +299,18 @@ private function populateCustomerWithSecureData($customerModel, $passwordHash = } } - /** - * Retrieve customer. - * - * @param string $email - * @param int|null $websiteId - * @return \Magento\Customer\Api\Data\CustomerInterface - * @throws \Magento\Framework\Exception\NoSuchEntityException If customer with the specified email does not exist. - * @throws \Magento\Framework\Exception\LocalizedException - */ public function get($email, $websiteId = null) { $customerModel = $this->customerRegistry->retrieveByEmail($email, $websiteId); return $customerModel->getDataModel(); } - /** - * Get customer by Customer ID. - * - * @param int $customerId - * @return \Magento\Customer\Api\Data\CustomerInterface - * @throws \Magento\Framework\Exception\NoSuchEntityException If customer with the specified ID does not exist. - * @throws \Magento\Framework\Exception\LocalizedException - */ public function getById($customerId) { $customerModel = $this->customerRegistry->retrieve($customerId); return $customerModel->getDataModel(); } - /** - * Retrieve customers which match a specified criteria. - * - * {@inheritdoc} - * - * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria - * @return \Magento\Customer\Api\Data\CustomerSearchResultsInterface - * @throws \Magento\Framework\Exception\LocalizedException - */ public function getList(SearchCriteriaInterface $searchCriteria) { $searchResults = $this->searchResultsFactory->create(); @@ -374,26 +348,11 @@ public function getList(SearchCriteriaInterface $searchCriteria) return $searchResults; } - /** - * Delete customer. - * - * @param \Magento\Customer\Api\Data\CustomerInterface $customer - * @return bool true on success - * @throws \Magento\Framework\Exception\LocalizedException - */ public function delete(CustomerInterface $customer) { return $this->deleteById($customer->getId()); } - /** - * Delete customer by Customer ID. - * - * @param int $customerId - * @return bool true on success - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @throws \Magento\Framework\Exception\LocalizedException - */ public function deleteById($customerId) { $customerModel = $this->customerRegistry->retrieve($customerId); From 5ba0f1d01ed3386522d84d02b2c35070a81fe3d3 Mon Sep 17 00:00:00 2001 From: francesco Date: Fri, 5 Oct 2018 09:46:20 +0200 Subject: [PATCH 003/142] Fix phpdocumentor - comment blocks are not automatically inherited --- app/code/Magento/Customer/Model/Address.php | 10 +++++ .../ResourceModel/CustomerRepository.php | 43 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/app/code/Magento/Customer/Model/Address.php b/app/code/Magento/Customer/Model/Address.php index 1206f157c7fc5..a10c6569851f6 100644 --- a/app/code/Magento/Customer/Model/Address.php +++ b/app/code/Magento/Customer/Model/Address.php @@ -169,6 +169,16 @@ public function updateData(AddressInterface $address) return $this; } + /** + * Create address data object based on current address model. + * + * @param int|null $defaultBillingAddressId + * @param int|null $defaultShippingAddressId + * @return AddressInterface + * Use Api/Data/AddressInterface as a result of service operations. Don't rely on the model to provide + * the instance of Api/Data/AddressInterface + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ public function getDataModel($defaultBillingAddressId = null, $defaultShippingAddressId = null) { if ($this->getCustomerId() || $this->getParentId()) { diff --git a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php index e90aa5e319c65..d3b7e2c6a28f7 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php +++ b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php @@ -299,18 +299,46 @@ private function populateCustomerWithSecureData($customerModel, $passwordHash = } } + /** + * Retrieve customer. + * + * @param string $email + * @param int|null $websiteId + * @return \Magento\Customer\Api\Data\CustomerInterface + * @throws \Magento\Framework\Exception\NoSuchEntityException If customer with the specified email does not exist. + * @throws \Magento\Framework\Exception\LocalizedException + */ public function get($email, $websiteId = null) { $customerModel = $this->customerRegistry->retrieveByEmail($email, $websiteId); return $customerModel->getDataModel(); } + /** + * Get customer by Customer ID. + * + * @param int $customerId + * @return \Magento\Customer\Api\Data\CustomerInterface + * @throws \Magento\Framework\Exception\NoSuchEntityException If customer with the specified ID does not exist. + * @throws \Magento\Framework\Exception\LocalizedException + */ public function getById($customerId) { $customerModel = $this->customerRegistry->retrieve($customerId); return $customerModel->getDataModel(); } + /** + * Retrieve customers which match a specified criteria. + * + * This call returns an array of objects, but detailed information about each object’s attributes might not be + * included. See http://devdocs.magento.com/codelinks/attributes.html#CustomerRepositoryInterface to determine + * which call to use to get detailed information about all attributes for an object. + * + * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria + * @return \Magento\Customer\Api\Data\CustomerSearchResultsInterface + * @throws \Magento\Framework\Exception\LocalizedException + */ public function getList(SearchCriteriaInterface $searchCriteria) { $searchResults = $this->searchResultsFactory->create(); @@ -348,11 +376,26 @@ public function getList(SearchCriteriaInterface $searchCriteria) return $searchResults; } + /** + * Delete customer. + * + * @param \Magento\Customer\Api\Data\CustomerInterface $customer + * @return bool true on success + * @throws \Magento\Framework\Exception\LocalizedException + */ public function delete(CustomerInterface $customer) { return $this->deleteById($customer->getId()); } + /** + * Delete customer by Customer ID. + * + * @param int $customerId + * @return bool true on success + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\LocalizedException + */ public function deleteById($customerId) { $customerModel = $this->customerRegistry->retrieve($customerId); From ea894480d45be5a976a14a1a61410a1669166d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leandro=20Mel=C3=A3o=20Medeiros?= Date: Mon, 29 Oct 2018 16:15:02 -0300 Subject: [PATCH 004/142] Update ReferenceBlock Class Including the "class" attribute to the typeReferenceBlock definition allows you to update a block class when overriding or updating a layout.xml file without the need to remove the original block and re-add it with the same name but different class. --- lib/internal/Magento/Framework/View/Layout/etc/elements.xsd | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd index 39cdec05a65ea..6486b39070788 100755 --- a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd +++ b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd @@ -313,6 +313,7 @@ + From 6b9aa47cc9bb2574360858802444e546b091dbf9 Mon Sep 17 00:00:00 2001 From: Jaimin Sutariya Date: Fri, 14 Dec 2018 11:27:43 +0530 Subject: [PATCH 005/142] Resolved undefined index issue for import adapter --- .../ImportExport/Model/Import/Entity/AbstractEntity.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php index 1fc3257ff2c1e..2a861be1fe97b 100644 --- a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php +++ b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php @@ -408,7 +408,9 @@ protected function _saveValidatedBunches() if ($source->valid()) { try { $rowData = $source->current(); - $skuSet[$rowData['sku']] = true; + if (array_key_exists('sku', $rowData)) { + $skuSet[$rowData['sku']] = true; + } } catch (\InvalidArgumentException $e) { $this->addRowError($e->getMessage(), $this->_processedRowsCount); $this->_processedRowsCount++; From 939b665d3b2b8e0f717c61a8c746b6a602156724 Mon Sep 17 00:00:00 2001 From: Jaimin Sutariya Date: Sat, 22 Dec 2018 11:06:42 +0530 Subject: [PATCH 006/142] Updated code to get Entity count for product import --- .../Magento/ImportExport/Model/Import/Entity/AbstractEntity.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php index 2a861be1fe97b..10b29a50a4064 100644 --- a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php +++ b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php @@ -438,7 +438,7 @@ protected function _saveValidatedBunches() $source->next(); } } - $this->_processedEntitiesCount = count($skuSet); + $this->_processedEntitiesCount = (count($skuSet)) ? : $this->_processedRowsCount; return $this; } From b28830d8f6e770c28310503027b51dd906807bef Mon Sep 17 00:00:00 2001 From: Vova Yatsyuk Date: Thu, 27 Dec 2018 11:08:58 +0200 Subject: [PATCH 007/142] Show widget image despite of 'type_name' availability. This commit fixes widget previews for widgets inserted in Magento < 2.3, when 'type_name' property doesn't exist --- .../wysiwyg/tiny_mce/plugins/magentowidget/editor_plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentowidget/editor_plugin.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentowidget/editor_plugin.js index 18d71aad2071a..bac083d7cdeaf 100644 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentowidget/editor_plugin.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentowidget/editor_plugin.js @@ -132,7 +132,7 @@ define([ attributes.type = attributes.type.replace(/\\\\/g, '\\'); imageSrc = config.placeholders[attributes.type]; - if (config.types.indexOf(attributes['type_name']) > -1) { + if (imageSrc) { imageHtml += ''; } else { From 982d31cf3550490d46c02c230f3eb1d0aac6d7da Mon Sep 17 00:00:00 2001 From: Vova Yatsyuk Date: Thu, 27 Dec 2018 11:12:43 +0200 Subject: [PATCH 008/142] Don't add additional parameter to the widget code. This commit makes cleaner widget code. Widget name can be taken from plugin options by 'type' property --- app/code/Magento/Widget/Model/Widget.php | 2 -- app/code/Magento/Widget/Model/Widget/Config.php | 2 +- .../wysiwyg/tiny_mce/plugins/magentowidget/editor_plugin.js | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Widget/Model/Widget.php b/app/code/Magento/Widget/Model/Widget.php index 5ba03d008ded0..5cfbfbf9cdf41 100644 --- a/app/code/Magento/Widget/Model/Widget.php +++ b/app/code/Magento/Widget/Model/Widget.php @@ -323,8 +323,6 @@ public function getWidgetDeclaration($type, $params = [], $asIs = true) $directive .= $this->getWidgetPageVarName($params); - $directive .= sprintf(' type_name="%s"', $widget['name']); - $directive .= '}}'; if ($asIs) { diff --git a/app/code/Magento/Widget/Model/Widget/Config.php b/app/code/Magento/Widget/Model/Widget/Config.php index 4f81ef33f47f7..5832a08f0df06 100644 --- a/app/code/Magento/Widget/Model/Widget/Config.php +++ b/app/code/Magento/Widget/Model/Widget/Config.php @@ -202,7 +202,7 @@ public function getAvailableWidgets($config) if (is_array($skipped) && in_array($widget['type'], $skipped)) { continue; } - $result[] = $widget['name']->getText(); + $result[$widget['type']] = $widget['name']->getText(); } } diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentowidget/editor_plugin.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentowidget/editor_plugin.js index bac083d7cdeaf..cfcdef0b701c9 100644 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentowidget/editor_plugin.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentowidget/editor_plugin.js @@ -147,8 +147,8 @@ define([ imageHtml += ' src="' + imageSrc + '"'; imageHtml += ' />'; - if (attributes['type_name']) { - imageHtml += attributes['type_name']; + if (config.types[attributes.type]) { + imageHtml += config.types[attributes.type]; } imageHtml += ''; From fcfb66b6d34327fee57759e510bee8d415cce3cf Mon Sep 17 00:00:00 2001 From: Vova Yatsyuk Date: Thu, 27 Dec 2018 14:50:20 +0200 Subject: [PATCH 009/142] Fixed failing tests --- app/code/Magento/Widget/Test/Unit/Model/WidgetTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/Widget/Test/Unit/Model/WidgetTest.php b/app/code/Magento/Widget/Test/Unit/Model/WidgetTest.php index 5c546d7e2435c..850a3fbe83211 100644 --- a/app/code/Magento/Widget/Test/Unit/Model/WidgetTest.php +++ b/app/code/Magento/Widget/Test/Unit/Model/WidgetTest.php @@ -224,7 +224,6 @@ public function testGetWidgetDeclaration() $this->assertContains('title="my "widget""', $result); $this->assertContains('conditions_encoded="encoded-conditions-string"', $result); $this->assertContains('page_var_name="pasdf"', $result); - $this->assertContains('type_name=""}}', $result); } /** @@ -275,7 +274,6 @@ public function testGetWidgetDeclarationWithZeroValueParam() ); $this->assertContains('{{widget type="Magento\CatalogWidget\Block\Product\ProductsList"', $result); $this->assertContains('page_var_name="pasdf"', $result); - $this->assertContains('type_name=""}}', $result); $this->assertContains('products_count=""', $result); } } From fa22418f6f0fd629b440c171e883d6242c0f32bb Mon Sep 17 00:00:00 2001 From: eduard13 Date: Wed, 6 Feb 2019 09:44:37 +0200 Subject: [PATCH 010/142] Fixing the multidimensional array as value for the widget's parameter --- .../Magento/Widget/Block/Adminhtml/Widget/Options.php | 4 +++- .../Magento/Framework/Data/Form/Element/Label.php | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Widget/Block/Adminhtml/Widget/Options.php b/app/code/Magento/Widget/Block/Adminhtml/Widget/Options.php index cc2af4996d562..829741786316d 100644 --- a/app/code/Magento/Widget/Block/Adminhtml/Widget/Options.php +++ b/app/code/Magento/Widget/Block/Adminhtml/Widget/Options.php @@ -166,7 +166,9 @@ protected function _addField($parameter) if (is_array($data['value'])) { foreach ($data['value'] as &$value) { - $value = html_entity_decode($value); + if (!is_array($value)) { + $value = html_entity_decode($value); + } } } else { $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 901dcb5289e8d..a95c7646eadce 100644 --- a/lib/internal/Magento/Framework/Data/Form/Element/Label.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Label.php @@ -37,8 +37,14 @@ public function __construct( public function getElementHtml() { $html = $this->getBold() ? '
' : '
'; - $html .= $this->getEscapedValue() . '
'; + if (is_array($this->getValue())) { + $html .= '
'; + } else { + $html .= $this->getEscapedValue() . ''; + } + $html .= $this->getAfterElementHtml(); + return $html; } } From f35392661962f824a474a260618a9bb8ec41549e Mon Sep 17 00:00:00 2001 From: eduard13 Date: Wed, 6 Feb 2019 12:31:31 +0200 Subject: [PATCH 011/142] Refactoring the if condition --- lib/internal/Magento/Framework/Data/Form/Element/Label.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Label.php b/lib/internal/Magento/Framework/Data/Form/Element/Label.php index a95c7646eadce..a2efb72c75542 100644 --- a/lib/internal/Magento/Framework/Data/Form/Element/Label.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Label.php @@ -37,12 +37,11 @@ public function __construct( public function getElementHtml() { $html = $this->getBold() ? '
' : '
'; - if (is_array($this->getValue())) { - $html .= '
'; - } else { - $html .= $this->getEscapedValue() . '
'; + if (!is_array($this->getValue())) { + $html .= $this->getEscapedValue(); } + $html .= ''; $html .= $this->getAfterElementHtml(); return $html; From 7eb567e48314c8e2f290838b3eefd23656e58eb7 Mon Sep 17 00:00:00 2001 From: eduard13 Date: Thu, 7 Feb 2019 13:25:45 +0200 Subject: [PATCH 012/142] Applying some minor adjustments --- app/code/Magento/Widget/Block/Adminhtml/Widget/Options.php | 2 +- lib/internal/Magento/Framework/Data/Form/Element/Label.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Widget/Block/Adminhtml/Widget/Options.php b/app/code/Magento/Widget/Block/Adminhtml/Widget/Options.php index 829741786316d..43761d4d4ef2d 100644 --- a/app/code/Magento/Widget/Block/Adminhtml/Widget/Options.php +++ b/app/code/Magento/Widget/Block/Adminhtml/Widget/Options.php @@ -166,7 +166,7 @@ protected function _addField($parameter) if (is_array($data['value'])) { foreach ($data['value'] as &$value) { - if (!is_array($value)) { + if (is_string($value)) { $value = html_entity_decode($value); } } diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Label.php b/lib/internal/Magento/Framework/Data/Form/Element/Label.php index a2efb72c75542..d9834b8c15ee1 100644 --- a/lib/internal/Magento/Framework/Data/Form/Element/Label.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Label.php @@ -37,7 +37,7 @@ public function __construct( public function getElementHtml() { $html = $this->getBold() ? '
' : '
'; - if (!is_array($this->getValue())) { + if (is_string($this->getValue())) { $html .= $this->getEscapedValue(); } From c276064c31714bb21c494e5dc45e8ffe8217c333 Mon Sep 17 00:00:00 2001 From: Veronika Kurochkina Date: Tue, 12 Feb 2019 13:27:31 +0300 Subject: [PATCH 013/142] MAGETWO-65232: Product name does not display special characters properly - Fix product name with special characters in product grid --- .../Catalog/view/adminhtml/ui_component/product_listing.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml index 65090fa3ac461..ad4a9d8103704 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml @@ -132,6 +132,7 @@ true text + ui/grid/cells/html From f53d78df6dbcdc1233acd89991579d40d07fd045 Mon Sep 17 00:00:00 2001 From: alexander-aleman <35915533+alexander-aleman@users.noreply.github.com> Date: Thu, 14 Feb 2019 08:21:17 +0100 Subject: [PATCH 014/142] Pass $websiteId as a parameter instead of $storeId The method getProductPriceData expects $websiteId as a parameter, but $storeId was given. It should be $websiteId since prices are website specific. Also see \Magento\Elasticsearch\Elasticsearch5\Model\Adapter\DataMapper\ProductDataMapper where a similar method exists and $websiteId is used. --- .../Model/Adapter/BatchDataMapper/PriceFieldsProvider.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Elasticsearch/Model/Adapter/BatchDataMapper/PriceFieldsProvider.php b/app/code/Magento/Elasticsearch/Model/Adapter/BatchDataMapper/PriceFieldsProvider.php index 875d384a20596..56c84593256be 100644 --- a/app/code/Magento/Elasticsearch/Model/Adapter/BatchDataMapper/PriceFieldsProvider.php +++ b/app/code/Magento/Elasticsearch/Model/Adapter/BatchDataMapper/PriceFieldsProvider.php @@ -72,13 +72,15 @@ public function __construct( */ public function getFields(array $productIds, $storeId) { + $websiteId = $this->storeManager->getStore($storeId)->getWebsiteId(); + $priceData = $this->dataProvider->getSearchableAttribute('price') ? $this->resourceIndex->getPriceIndexData($productIds, $storeId) : []; $fields = []; foreach ($productIds as $productId) { - $fields[$productId] = $this->getProductPriceData($productId, $storeId, $priceData); + $fields[$productId] = $this->getProductPriceData($productId, $websiteId, $priceData); } return $fields; From a34d4f5e62b4bb0a459179ccd209af952b41489f Mon Sep 17 00:00:00 2001 From: Veronika Kurochkina Date: Thu, 14 Feb 2019 12:12:53 +0300 Subject: [PATCH 015/142] MAGETWO-65232: Product name does not display special characters properly - Fix product name with special characters in invoice ans shipment pdf --- .../Model/Order/Pdf/Items/Invoice/DefaultInvoice.php | 9 +++++++-- .../Model/Order/Pdf/Items/Shipment/DefaultShipment.php | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) 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 8562328025540..9c183ed44c72a 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 @@ -66,11 +66,16 @@ public function draw() $lines = []; // draw Product name - $lines[0] = [['text' => $this->string->split($item->getName(), 35, true, true), 'feed' => 35]]; + $lines[0] = [ + [ + 'text' => $this->string->split(html_entity_decode($item->getName()), 35, true, true), + 'feed' => 35 + ] + ]; // draw SKU $lines[0][] = [ - 'text' => $this->string->split($this->getSku($item), 17), + '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 6007e1dcf2b47..c175b9866fb8e 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 @@ -65,14 +65,19 @@ public function draw() $lines = []; // draw Product name - $lines[0] = [['text' => $this->string->split($item->getName(), 60, true, true), 'feed' => 100]]; + $lines[0] = [ + [ + 'text' => $this->string->split(html_entity_decode($item->getName()), 60, true, true), + 'feed' => 100 + ] + ]; // draw QTY $lines[0][] = ['text' => $item->getQty() * 1, 'feed' => 35]; // draw SKU $lines[0][] = [ - 'text' => $this->string->split($this->getSku($item), 25), + 'text' => $this->string->split(html_entity_decode($this->getSku($item)), 25), 'feed' => 565, 'align' => 'right', ]; From 4a214364eb0b3fb06cc9acd92747c67505fdf539 Mon Sep 17 00:00:00 2001 From: Nikita Chubukov Date: Fri, 15 Feb 2019 14:42:08 +0300 Subject: [PATCH 016/142] MAGETWO-58219: Product Attribute Option Values for storeview instead of admin on product creation - Changed logic of displaying attribute option values in admin panel --- .../DataProvider/Product/Form/Modifier/Eav.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) mode change 100755 => 100644 app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php old mode 100755 new mode 100644 index 99f7122efa0a8..c96fe54a87620 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -35,6 +35,7 @@ use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav\CompositeConfigProcessor; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Eav\Model\ResourceModel\Entity\Attribute\CollectionFactory as AttributeCollectionFactory; +use Magento\Framework\App\State; /** * Class Eav @@ -213,6 +214,11 @@ class Eav extends AbstractModifier */ private $scopeConfig; + /** + * @var State + */ + private $state; + /** * Eav constructor. * @param LocatorInterface $locator @@ -237,6 +243,7 @@ class Eav extends AbstractModifier * @param CompositeConfigProcessor|null $wysiwygConfigProcessor * @param ScopeConfigInterface|null $scopeConfig * @param AttributeCollectionFactory $attributeCollectionFactory + * @param State $state * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -261,7 +268,8 @@ public function __construct( $attributesToEliminate = [], CompositeConfigProcessor $wysiwygConfigProcessor = null, ScopeConfigInterface $scopeConfig = null, - AttributeCollectionFactory $attributeCollectionFactory = null + AttributeCollectionFactory $attributeCollectionFactory = null, + State $state = null ) { $this->locator = $locator; $this->catalogEavValidationRules = $catalogEavValidationRules; @@ -288,6 +296,8 @@ public function __construct( ->get(ScopeConfigInterface::class); $this->attributeCollectionFactory = $attributeCollectionFactory ?: \Magento\Framework\App\ObjectManager::getInstance()->get(AttributeCollectionFactory::class); + $this->state = $state ?: \Magento\Framework\App\ObjectManager::getInstance() + ->get(State::class); } /** @@ -676,7 +686,9 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC // TODO: Refactor to $attribute->getOptions() when MAGETWO-48289 is done $attributeModel = $this->getAttributeModel($attribute); if ($attributeModel->usesSource()) { - $options = $attributeModel->getSource()->getAllOptions(); + $options = ($this->state->getAreaCode() == \Magento\Framework\App\Area::AREA_ADMINHTML) + ? $attributeModel->getSource()->getAllOptions(true, true) + : $attributeModel->getSource()->getAllOptions(); $meta = $this->arrayManager->merge($configPath, $meta, [ 'options' => $this->convertOptionsValueToString($options), ]); From ea4a5ec6a150474d7731418c995ded75a55f1bea Mon Sep 17 00:00:00 2001 From: Veronika Kurochkina Date: Mon, 18 Feb 2019 13:06:36 +0300 Subject: [PATCH 017/142] MAGETWO-65232: Product name does not display special characters properly - Fix product name with special characters --- .../view/adminhtml/ui_component/product_listing.xml | 1 + .../Order/Pdf/Items/Creditmemo/DefaultCreditmemo.php | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml index ad4a9d8103704..d2d6f098125ce 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml @@ -155,6 +155,7 @@ text + ui/grid/cells/html 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 11908864236f6..882fec2ab7c46 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 @@ -66,11 +66,16 @@ public function draw() $lines = []; // draw Product name - $lines[0] = [['text' => $this->string->split($item->getName(), 35, true, true), 'feed' => 35]]; + $lines[0] = [ + [ + 'text' => $this->string->split(html_entity_decode($item->getName()), 35, true, true), + 'feed' => 35 + ] + ]; // draw SKU $lines[0][] = [ - 'text' => $this->string->split($this->getSku($item), 17), + 'text' => $this->string->split(html_entity_decode($this->getSku($item)), 17), 'feed' => 255, 'align' => 'right', ]; From e619c008b66854be09b093a149bb4b35d027218b Mon Sep 17 00:00:00 2001 From: Alexey Yakimovich Date: Mon, 18 Feb 2019 17:20:29 +0300 Subject: [PATCH 018/142] MAGETWO-70232: [GITHUB] Import customizable options adds it to another product if same SKU is filled#9457 - Fixed an issue with incorrect saving of imported custom options when product sku was changed; --- app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php index 0941aa2478935..43d496c37ca69 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php @@ -58,7 +58,11 @@ public function execute($entity, $arguments = []) } } if ($options) { + $hasChangedSku = $entity->dataHasChangedFor('sku'); foreach ($options as $option) { + if ($hasChangedSku) { + $option->setProductSku($entity->getSku()); + } $this->optionRepository->save($option); } } From f1b43abc82c370ef4c48d684ae59313345c37893 Mon Sep 17 00:00:00 2001 From: Nikita Chubukov Date: Wed, 20 Feb 2019 10:43:41 +0300 Subject: [PATCH 019/142] MAGETWO-58226: Calendar Custom Options are displayed broken on Storefront - Preventing error messages below each select field for Customizable Options --- .../frontend/Magento/blank/web/css/source/_forms.less | 10 ++++++++++ .../frontend/Magento/luma/web/css/source/_forms.less | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/app/design/frontend/Magento/blank/web/css/source/_forms.less b/app/design/frontend/Magento/blank/web/css/source/_forms.less index c9f3c3d72ef4c..6ad1f3bf38eb9 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_forms.less +++ b/app/design/frontend/Magento/blank/web/css/source/_forms.less @@ -101,6 +101,16 @@ .lib-form-validation-note(); } + .product-options-wrapper { + .date { + &.required { + div[for*='options'] { + display: none !important; + } + } + } + } + .field .tooltip { .lib-tooltip(right); .tooltip-content { diff --git a/app/design/frontend/Magento/luma/web/css/source/_forms.less b/app/design/frontend/Magento/luma/web/css/source/_forms.less index 98dd57dead74c..78a50ba10c9bf 100644 --- a/app/design/frontend/Magento/luma/web/css/source/_forms.less +++ b/app/design/frontend/Magento/luma/web/css/source/_forms.less @@ -113,6 +113,16 @@ .lib-form-validation-note(); } + .product-options-wrapper { + .required { + div[for*='options'] { + &.mage-error { + display: none !important; + } + } + } + } + // TEMP .field .tooltip { From 0ff3e0ea40d2558fd3afbf809d26403d066b25db Mon Sep 17 00:00:00 2001 From: Nikita Chubukov Date: Thu, 21 Feb 2019 16:02:26 +0300 Subject: [PATCH 020/142] MAGETWO-58226: Calendar Custom Options are displayed broken on Storefront - Preventing error messages below each field of date type for Customizable Options --- .../frontend/Magento/blank/web/css/source/_forms.less | 4 +++- .../frontend/Magento/luma/web/css/source/_forms.less | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/design/frontend/Magento/blank/web/css/source/_forms.less b/app/design/frontend/Magento/blank/web/css/source/_forms.less index 6ad1f3bf38eb9..26f5ff89e99e3 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_forms.less +++ b/app/design/frontend/Magento/blank/web/css/source/_forms.less @@ -105,7 +105,9 @@ .date { &.required { div[for*='options'] { - display: none !important; + &.mage-error { + display: none !important; + } } } } diff --git a/app/design/frontend/Magento/luma/web/css/source/_forms.less b/app/design/frontend/Magento/luma/web/css/source/_forms.less index 78a50ba10c9bf..047ffd18d352f 100644 --- a/app/design/frontend/Magento/luma/web/css/source/_forms.less +++ b/app/design/frontend/Magento/luma/web/css/source/_forms.less @@ -114,10 +114,12 @@ } .product-options-wrapper { - .required { - div[for*='options'] { - &.mage-error { - display: none !important; + .date { + &.required { + div[for*='options'] { + &.mage-error { + display: none !important; + } } } } From ffbf8e6da2f597dbb6d8ad6cfbe628903721648d Mon Sep 17 00:00:00 2001 From: Alexey Yakimovich Date: Mon, 15 Oct 2018 15:55:13 +0300 Subject: [PATCH 021/142] MAGETWO-64838: Unable to create order from store front if customer address custom attribute is required. - Fixed an issue witn incorrent work of file/image custom attributes on checkout; --- .../Controller/Address/File/Upload.php | 146 ++++++ .../Magento/Customer/Model/FileProcessor.php | 5 +- .../base/web/js/form/element/file-uploader.js | 3 +- .../web/js/form/element/image-uploader.js | 3 +- .../form/element/uploader/uploader.html | 37 ++ .../css/source/module/checkout/_checkout.less | 2 + .../checkout/fields/_file-uploader.less | 450 ++++++++++++++++++ .../Magento/luma/web/css/source/_forms.less | 4 + .../CustomAttribute/PreprocessorInterface.php | 29 ++ .../Webapi/ServiceInputProcessor.php | 30 +- lib/web/css/source/lib/variables/_colors.less | 10 + 11 files changed, 712 insertions(+), 7 deletions(-) create mode 100644 app/code/Magento/Customer/Controller/Address/File/Upload.php create mode 100644 app/code/Magento/Ui/view/frontend/web/templates/form/element/uploader/uploader.html create mode 100644 app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/fields/_file-uploader.less create mode 100644 lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php diff --git a/app/code/Magento/Customer/Controller/Address/File/Upload.php b/app/code/Magento/Customer/Controller/Address/File/Upload.php new file mode 100644 index 0000000000000..dbbea482b0e52 --- /dev/null +++ b/app/code/Magento/Customer/Controller/Address/File/Upload.php @@ -0,0 +1,146 @@ +fileUploaderFactory = $fileUploaderFactory; + $this->addressMetadataService = $addressMetadataService; + $this->logger = $logger; + $this->fileProcessorFactory = $fileProcessorFactory; + parent::__construct($context); + } + + /** + * @inheritDoc + */ + public function execute() + { + try { + $requestedFiles = $this->getRequest()->getFiles('custom_attributes'); + if (empty($requestedFiles)) { + $result = $this->processError(__('No files for upload.')); + } else { + $attributeCode = key($requestedFiles); + $attributeMetadata = $this->addressMetadataService->getAttributeMetadata($attributeCode); + + /** @var FileUploader $fileUploader */ + $fileUploader = $this->fileUploaderFactory->create([ + 'attributeMetadata' => $attributeMetadata, + 'entityTypeCode' => AddressMetadataInterface::ENTITY_TYPE_ADDRESS, + 'scope' => CustomAttributesDataInterface::CUSTOM_ATTRIBUTES, + ]); + + $errors = $fileUploader->validate(); + if (true !== $errors) { + $errorMessage = implode('
', $errors); + $result = $this->processError(($errorMessage)); + } else { + $result = $fileUploader->upload(); + } + } + } catch (LocalizedException $e) { + $result = $this->processError($e->getMessage(), $e->getCode()); + } catch (\Exception $e) { + $this->logger->critical($e); + $result = $this->processError($e->getMessage(), $e->getCode()); + } + + $this->moveTmpFileToSuitableFolder($result); + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON); + $resultJson->setData($result); + return $resultJson; + } + + /** + * Move file from temporary folder to the 'customer_address' media folder + * + * @param array $fileInfo + * @throws LocalizedException + */ + private function moveTmpFileToSuitableFolder(&$fileInfo) + { + $fileName = $fileInfo['file']; + $fileProcessor = $this->fileProcessorFactory + ->create(['entityTypeCode' => AddressMetadataInterface::ENTITY_TYPE_ADDRESS]); + + $newFilePath = $fileProcessor->moveTemporaryFile($fileName); + $fileInfo['file'] = $newFilePath; + $fileInfo['url'] = $fileProcessor->getViewUrl( + $newFilePath, + 'file' + ); + } + + /** + * Prepare result array for errors + * + * @param string $message + * @param int $code + * @return array + */ + private function processError($message, $code = 0) + { + $result = [ + 'error' => $message, + 'errorcode' => $code, + ]; + + return $result; + } +} diff --git a/app/code/Magento/Customer/Model/FileProcessor.php b/app/code/Magento/Customer/Model/FileProcessor.php index 6a8472758c169..e7e235b31fe49 100644 --- a/app/code/Magento/Customer/Model/FileProcessor.php +++ b/app/code/Magento/Customer/Model/FileProcessor.php @@ -5,6 +5,9 @@ */ namespace Magento\Customer\Model; +/** + * Processor class for work with uploaded files + */ class FileProcessor { /** @@ -232,7 +235,7 @@ public function moveTemporaryFile($fileName) ); } - $fileName = $dispersionPath . '/' . $fileName; + $fileName = $dispersionPath . '/' . $destinationFileName; return $fileName; } diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js b/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js index 2c5bc1159dd3a..f28569caa0053 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js @@ -16,7 +16,8 @@ define([ 'Magento_Ui/js/form/element/abstract', 'mage/backend/notification', 'mage/translate', - 'jquery/file-uploader' + 'jquery/file-uploader', + 'mage/adminhtml/tools' ], function ($, _, utils, uiAlert, validator, Element, notification, $t) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/image-uploader.js b/app/code/Magento/Ui/view/base/web/js/form/element/image-uploader.js index 0ae09f14fa946..b490ac557e71b 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/image-uploader.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/image-uploader.js @@ -11,8 +11,7 @@ define([ 'Magento_Ui/js/modal/alert', 'Magento_Ui/js/lib/validation/validator', 'Magento_Ui/js/form/element/file-uploader', - 'mage/adminhtml/browser', - 'mage/adminhtml/tools' + 'mage/adminhtml/browser' ], function ($, _, utils, uiAlert, validator, Element, browser) { 'use strict'; diff --git a/app/code/Magento/Ui/view/frontend/web/templates/form/element/uploader/uploader.html b/app/code/Magento/Ui/view/frontend/web/templates/form/element/uploader/uploader.html new file mode 100644 index 0000000000000..226ad2915bb61 --- /dev/null +++ b/app/code/Magento/Ui/view/frontend/web/templates/form/element/uploader/uploader.html @@ -0,0 +1,37 @@ + + +
+
+
+ +
+ + + +
+ +
+ + + +
+ +
+
+ +
diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_checkout.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_checkout.less index 3ea1f5b7f6842..ac5ab0d87bf62 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_checkout.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_checkout.less @@ -7,6 +7,8 @@ // Variables // _____________________________________________ +@import 'fields/_file-uploader.less'; + @checkout-wrapper__margin: @indent__base; @checkout-wrapper__columns: 16; diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/fields/_file-uploader.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/fields/_file-uploader.less new file mode 100644 index 0000000000000..7b06186ef9ad3 --- /dev/null +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/fields/_file-uploader.less @@ -0,0 +1,450 @@ +// /** +// * Copyright © Magento, Inc. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Components -> Single File Uploader +// _____________________________________________ + +// +// Variables +// --------------------------------------------- + +@icon-delete__content: '\e604'; +@icon-file__content: '\e626'; + + +@file-uploader-preview__border-color: @color-lighter-grayish; +@file-uploader-preview__background-color: @color-white; +@file-uploader-preview-focus__color: @color-blue2; + +@file-uploader-document-icon__color: @color-gray80; +@file-uploader-document-icon__size: 7rem; +@file-uploader-document-icon__z-index: @data-grid-file-uploader-image__z-index + 1; + +@file-uploader-video-icon__color: @color-gray80; +@file-uploader-video-icon__size: 4rem; +@file-uploader-video-icon__z-index: @data-grid-file-uploader-image__z-index + 1; + +@file-uploader-placeholder-icon__color: @color-gray80; +@file-uploader-placeholder-icon__z-index: @data-grid-file-uploader-image__z-index + 1; + +@file-uploader-delete-icon__color: @color-brownie; +@file-uploader-delete-icon__hover__color: @color-brownie-vanilla; +@file-uploader-delete-icon__font-size: 1.6rem; + +@file-uploader-muted-text__color: @color-gray62; + +@file-uploader-preview__width: 150px; +@file-uploader-preview__height: @file-uploader-preview__width; +@file-uploader-preview__opacity: .7; + +@file-uploader-spinner-dimensions: 15px; + +@file-uploader-dragover__background: @color-gray83; +@file-uploader-dragover-focus__color: @color-blue2; + +// Grid uploader + +@data-grid-file-uploader-image__size: 5rem; +@data-grid-file-uploader-image__z-index: 1; + +@data-grid-file-uploader-menu-button__width: 2rem; + +@data-grid-file-uploader-upload-icon__color: @color-darkie-gray; +@data-grid-file-uploader-upload-icon__hover__color: @color-very-dark-gray; +@data-grid-file-uploader-upload-icon__line-height: 48px; + +@data-grid-file-uploader-wrapper__size: @data-grid-file-uploader-image__size + 2rem; + +// +// Single file uploader +// --------------------------------------------- + +.file-uploader-area { + position: relative; + + input[type='file'] { + cursor: pointer; + opacity: 0; + overflow: hidden; + position: absolute; + visibility: hidden; + width: 0; + + &:focus { + + .file-uploader-button { + box-shadow: 0 0 0 1px @file-uploader-preview-focus__color; + } + } + + &:disabled { + + .file-uploader-button { + cursor: default; + opacity: .5; + pointer-events: none; + } + } + } +} + +.file-uploader-summary { + display: inline-block; + vertical-align: top; +} + +.file-uploader-button { + background: @color-gray-darken0; + border: 1px solid @color-gray_light; + box-sizing: border-box; + color: @color-black_dark; + cursor: pointer; + display: inline-block; + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-size: 1.4rem; + font-weight: 600; + line-height: 1.6rem; + margin: 0; + padding: 7px 15px; + vertical-align: middle; + + &._is-dragover { + background: @file-uploader-dragover__background; + border: 1px solid @file-uploader-preview-focus__color; + } +} + +.file-uploader-spinner { + background-image: url('@{baseDir}images/loader-1.gif'); + background-position: 50%; + background-repeat: no-repeat; + background-size: @file-uploader-spinner-dimensions; + display: none; + height: 30px; + margin-left: @indent__s; + vertical-align: top; + width: @file-uploader-spinner-dimensions; +} + +.file-uploader-preview { + .action-remove { + &:extend(.abs-action-reset all); + .lib-icon-font ( + @icon-delete__content, + @_icon-font: @icons__font-name, + @_icon-font-size: @file-uploader-delete-icon__font-size, + @_icon-font-color: @file-uploader-delete-icon__color, + @_icon-font-color-hover: @file-uploader-delete-icon__hover__color, + @_icon-font-text-hide: true, + @_icon-font-display: block + ); + bottom: 4px; + cursor: pointer; + display: block; + height: 27px; + left: 6px; + padding: 2px; + position: absolute; + text-decoration: none; + width: 25px; + z-index: 2; + } + + &:hover { + .preview-image img, + .preview-link:before { + opacity: @file-uploader-preview__opacity; + } + } + + .preview-link { + display: block; + height: 100%; + } + + .preview-image img { + bottom: 0; + left: 0; + margin: auto; + max-height: 100%; + max-width: 100%; + position: absolute; + right: 0; + top: 0; + z-index: 1; + } + + .preview-video { + .lib-icon-font( + @icon-file__content, + @_icon-font: @icons__font-name, + @_icon-font-size: @file-uploader-video-icon__size, + @_icon-font-color: @file-uploader-video-icon__color, + @_icon-font-color-hover: @file-uploader-video-icon__color + ); + + &:before { + left: 0; + margin-top: -@file-uploader-video-icon__size / 2; + position: absolute; + right: 0; + top: 50%; + z-index: @file-uploader-video-icon__z-index; + } + } + + .preview-document { + .lib-icon-font( + @icon-file__content, + @_icon-font: @icons__font-name, + @_icon-font-size: @file-uploader-document-icon__size, + @_icon-font-color: @file-uploader-document-icon__color, + @_icon-font-color-hover: @file-uploader-document-icon__color + ); + + &:before { + left: 0; + margin-top: -@file-uploader-document-icon__size / 2; + position: absolute; + right: 0; + top: 50%; + z-index: @file-uploader-document-icon__z-index; + } + } +} + +.file-uploader-preview, +.file-uploader-placeholder { + background: @file-uploader-preview__background-color; + border: 1px solid @file-uploader-preview__border-color; + box-sizing: border-box; + cursor: pointer; + display: block; + height: @file-uploader-preview__height; + line-height: 1; + margin: @indent__s @indent__m @indent__s 0; + overflow: hidden; + position: relative; + width: @file-uploader-preview__width; +} + +.file-uploader { + &._loading { + .file-uploader-spinner { + display: inline-block; + } + } + + .admin__field-note, + .admin__field-error { + margin-bottom: @indent__s; + } + + .file-uploader-filename { + .lib-text-overflow(); + max-width: @file-uploader-preview__width; + word-break: break-all; + + &:first-child { + margin-bottom: @indent__s; + } + } + + .file-uploader-meta { + color: @file-uploader-muted-text__color; + } + + .admin__field-fallback-reset { + margin-left: @indent__s; + } + + ._keyfocus & .action-remove { + &:focus { + box-shadow: 0 0 0 1px @file-uploader-preview-focus__color; + } + } +} + +// Placeholder for multiple uploader +.file-uploader-placeholder { + &.placeholder-document { + .lib-icon-font( + @icon-file__content, + @_icon-font: @icons__font-name, + @_icon-font-size: 5rem, + @_icon-font-color: @file-uploader-placeholder-icon__color, + @_icon-font-color-hover: @file-uploader-placeholder-icon__color + ); + + &:before { + left: 0; + position: absolute; + right: 0; + top: 20px; + z-index: @file-uploader-placeholder-icon__z-index; + } + } + + &.placeholder-image { + .lib-icon-font( + @icon-file__content, + @_icon-font: @icons__font-name, + @_icon-font-size: 5rem, + @_icon-font-color: @file-uploader-placeholder-icon__color, + @_icon-font-color-hover: @file-uploader-placeholder-icon__color + ); + + &:before { + left: 0; + position: absolute; + right: 0; + top: 20px; + z-index: @file-uploader-placeholder-icon__z-index; + } + } + + &.placeholder-video { + .lib-icon-font( + @icon-file__content, + @_icon-font: @icons__font-name, + @_icon-font-size: 3rem, + @_icon-font-color: @file-uploader-placeholder-icon__color, + @_icon-font-color-hover: @file-uploader-placeholder-icon__color + ); + + &:before { + left: 0; + position: absolute; + right: 0; + top: 30px; + z-index: @file-uploader-placeholder-icon__z-index; + } + } +} + +.file-uploader-placeholder-text { + bottom: 0; + color: @color-blue-dodger; + font-size: 1.1rem; + left: 0; + line-height: @line-height__base; + margin-bottom: 15%; + padding: 0 @indent__base; + position: absolute; + right: 0; + text-align: center; +} + +// +// Grid image uploader +// --------------------------------------------- + +.data-grid-file-uploader { + min-width: @data-grid-file-uploader-wrapper__size; + + &._loading { + .file-uploader-spinner { + display: block; + } + + .file-uploader-button { + &:before { + display: none; + } + } + } + + .file-uploader-image { + background: transparent; + bottom: 0; + left: 0; + margin: auto; + max-height: 100%; + max-width: 100%; + position: absolute; + right: 0; + top: 0; + z-index: @data-grid-file-uploader-image__z-index; + + + .file-uploader-area { + .file-uploader-button { + &:before { + display: none; + } + } + } + } + + .file-uploader-area { + z-index: @data-grid-file-uploader-image__z-index + 1; + } + + .file-uploader-spinner { + height: 100%; + margin: 0; + position: absolute; + top: 0; + width: 100%; + } + + .file-uploader-button { + display: block; + height: @data-grid-file-uploader-upload-icon__line-height; + text-align: center; + + .lib-icon-font ( + @icon-file__content, + @_icon-font: @icons__font-name, + @_icon-font-size: 1.3rem, + @_icon-font-line-height: @data-grid-file-uploader-upload-icon__line-height, + @_icon-font-color: @data-grid-file-uploader-upload-icon__color, + @_icon-font-color-hover: @data-grid-file-uploader-upload-icon__hover__color, + @_icon-font-text-hide: true, + @_icon-font-display: block + ); + } + + .action-select-wrap { + float: left; + + .action-select { + border: 1px solid @file-uploader-preview__border-color; + display: block; + height: @data-grid-file-uploader-image__size; + margin-left: -1px; + padding: 0; + width: @data-grid-file-uploader-menu-button__width; + + &:after { + border-color: @data-grid-file-uploader-upload-icon__color transparent transparent transparent; + left: 50%; + margin: 0 0 0 -5px; + } + + &:hover { + &:after { + border-color: @data-grid-file-uploader-upload-icon__hover__color transparent transparent transparent; + } + } + + > span { + display: none; + } + } + + .action-menu { + left: 4rem; + right: auto; + z-index: @data-grid-file-uploader-image__z-index + 1; + } + } +} + +.data-grid-file-uploader-inner { + border: 1px solid @file-uploader-preview__border-color; + float: left; + height: @data-grid-file-uploader-image__size; + position: relative; + width: @data-grid-file-uploader-image__size; +} diff --git a/app/design/frontend/Magento/luma/web/css/source/_forms.less b/app/design/frontend/Magento/luma/web/css/source/_forms.less index 98dd57dead74c..b92a2b5070b8f 100644 --- a/app/design/frontend/Magento/luma/web/css/source/_forms.less +++ b/app/design/frontend/Magento/luma/web/css/source/_forms.less @@ -104,6 +104,10 @@ .select-styling(); } + select.admin__control-multiselect { + height: auto; + } + .field-error, div.mage-error[generated] { margin-top: 7px; diff --git a/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php b/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php new file mode 100644 index 0000000000000..0f8743f057601 --- /dev/null +++ b/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php @@ -0,0 +1,29 @@ +typeProcessor = $typeProcessor; $this->objectManager = $objectManager; @@ -101,6 +109,7 @@ public function __construct( ?: \Magento\Framework\App\ObjectManager::getInstance()->get(ServiceTypeToEntityTypeMap::class); $this->config = $config ?: \Magento\Framework\App\ObjectManager::getInstance()->get(ConfigInterface::class); + $this->customAttributePreprocessors = $customAttributePreprocessors; } /** @@ -289,12 +298,11 @@ protected function convertCustomAttributeValue($customAttributesValueArray, $dat $dataObjectClassName = ltrim($dataObjectClassName, '\\'); foreach ($customAttributesValueArray as $key => $customAttribute) { + $this->runCustomAttributePreprocessors($key, $customAttribute); if (!is_array($customAttribute)) { $customAttribute = [AttributeValue::ATTRIBUTE_CODE => $key, AttributeValue::VALUE => $customAttribute]; } - list($customAttributeCode, $customAttributeValue) = $this->processCustomAttribute($customAttribute); - $entityType = $this->serviceTypeToEntityTypeMap->getEntityType($dataObjectClassName); if ($entityType) { $type = $this->customAttributeTypeLocator->getType( @@ -331,6 +339,22 @@ protected function convertCustomAttributeValue($customAttributesValueArray, $dat return $result; } + /** + * Prepare attribute value by loaded attribute preprocessors + * + * @param string $key + * @param mixed $customAttribute + * @return bool + */ + private function runCustomAttributePreprocessors($key, &$customAttribute) + { + foreach ($this->customAttributePreprocessors as $attributePreprocessor) { + if ($attributePreprocessor->shouldBePrepared($key, $customAttribute)) { + $attributePreprocessor->prepare($key, $customAttribute); + } + } + } + /** * Derive the custom attribute code and value. * diff --git a/lib/web/css/source/lib/variables/_colors.less b/lib/web/css/source/lib/variables/_colors.less index 9c694468e9f62..ffb0e8e797d81 100644 --- a/lib/web/css/source/lib/variables/_colors.less +++ b/lib/web/css/source/lib/variables/_colors.less @@ -7,9 +7,13 @@ // Color variables // _____________________________________________ +@color-blue-dodger: #008bdb; +@color-black_dark: #333333; + @color-white: #fff; @color-black: #000; +@color-darkie-gray: #8a837f; @color-gray19: #303030; @color-gray20: #333; @color-gray34: #575757; @@ -29,12 +33,16 @@ @color-gray79: #c9c9c9; @color-gray80: #ccc; @color-gray82: #d1d1d1; +@color-gray83: #d4d4d4; @color-gray89: #e3e3e3; @color-gray90: #e5e5e5; @color-gray91: #e8e8e8; @color-gray92: #ebebeb; @color-gray94: #f0f0f0; @color-gray95: #f2f2f2; +@color-gray_light: #cccccc; +@color-lighter-grayish: #cacaca; +@color-very-dark-gray: #666; @color-white-smoke: #f5f5f5; @color-white-dark-smoke: #efefef; @color-white-fog: #f8f8f8; @@ -80,6 +88,8 @@ @color-pink1: #fae5e5; @color-dark-pink1: #800080; // Legacy pink +@color-brownie: #514943; +@color-brownie-vanilla: #736963; @color-brownie1: #6f4400; @color-brownie-light1: #c07600; From 43e684f07a831481fd71e50d0d35196bedb4c9b7 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza Date: Tue, 26 Feb 2019 10:04:19 +0100 Subject: [PATCH 022/142] Place order concept --- .../Model/Resolver/PlaceOrder.php | 87 ++++++++++++++++++ .../Magento/QuoteGraphQl/etc/schema.graphqls | 13 +++ .../Magento/GraphQl/Quote/PlaceOrderTest.php | 91 +++++++++++++++++++ 3 files changed, 191 insertions(+) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/PlaceOrderTest.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php new file mode 100644 index 0000000000000..cb5fcf0dad5ab --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php @@ -0,0 +1,87 @@ +getCartForUser = $getCartForUser; + $this->cartManagement = $cartManagement; + $this->orderRepository = $orderRepository; + } + + /** + * @inheritdoc + */ + public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) + { + if (!isset($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); + + try { + $orderId = $this->cartManagement->placeOrder($cart->getId()); + $order = $this->orderRepository->get($orderId); + + // TODO: populate with data + return [ + 'order' => [ + 'order_id' => $order->getIncrementId() + ] + ]; + } catch (LocalizedException $exception) { + throw new GraphQlInputException( + __('Unable to place order: %message', ['message' => $exception->getMessage()]) + ); + } catch (\Exception $exception) { + throw new GraphQlInputException( + __('Unable to place order. An internal error occurred') + ); + } + } +} diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 2050a2d3ca790..263fef1feb361 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -14,6 +14,7 @@ type Mutation { setShippingAddressesOnCart(input: SetShippingAddressesOnCartInput): SetShippingAddressesOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetShippingAddressesOnCart") setBillingAddressOnCart(input: SetBillingAddressOnCartInput): SetBillingAddressOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetBillingAddressOnCart") setShippingMethodsOnCart(input: SetShippingMethodsOnCartInput): SetShippingMethodsOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetShippingMethodsOnCart") + placeOrder(input: PlaceOrderInput): PlaceOrderOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\PlaceOrder") } input AddSimpleProductsToCartInput { @@ -102,6 +103,10 @@ input ShippingMethodForAddressInput { method_code: String! } +input PlaceOrderInput { + cart_id: String! +} + type SetBillingAddressOnCartOutput { cart: Cart! } @@ -118,6 +123,10 @@ type ApplyCouponToCartOutput { cart: Cart! } +type PlaceOrderOutput { + order: Order! +} + type Cart { cart_id: String items: [CartItemInterface] @@ -242,3 +251,7 @@ type CartItemSelectedOptionValuePrice { units: String! type: PriceTypeEnum! } + +type Order { + order_id: String +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/PlaceOrderTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/PlaceOrderTest.php new file mode 100644 index 0000000000000..4871830e087ec --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/PlaceOrderTest.php @@ -0,0 +1,91 @@ +quoteResource = $objectManager->create(QuoteResource::class); + $this->quote = $objectManager->create(Quote::class); + $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_check_payment.php + */ + public function testPlaceOrder() + { + $reservedOrderId = 'test_order_1'; + $this->quoteResource->load( + $this->quote, + $reservedOrderId, + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + + $query =<<graphQlQuery($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('order_id', $response['placeOrder']['order']); + self::assertEquals($reservedOrderId, $response['placeOrder']['order']['order_id']); + } + + /** + * @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; + } +} From b099719a7fc18d84bd210f441e0e432ccb5d5af8 Mon Sep 17 00:00:00 2001 From: Lilit Sargsyan Date: Wed, 27 Feb 2019 12:33:18 +0400 Subject: [PATCH 023/142] MAGETWO-65232: Product name does not display special characters properly - Added automated test script. --- .../Magento/Catalog/Test/Mftf/Data/ConstData.xml | 4 ++++ .../Magento/Catalog/Test/Mftf/Data/ProductData.xml | 4 ++++ .../Test/Mftf/Section/AdminProductGridSection.xml | 1 + .../Mftf/Section/StorefrontNavigationSection.xml | 1 + .../Mftf/ActionGroup/AdminInvoiceActionGroup.xml | 12 ++++++++++++ 5 files changed, 22 insertions(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ConstData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ConstData.xml index 8a26b6babdbbc..d09880f14afbf 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ConstData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ConstData.xml @@ -13,4 +13,8 @@ 1 2 + + "Pursuit Lumaflex™ Tone Band" + "x™" + diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 6d0d953e44676..f6032fd307a84 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -35,6 +35,10 @@ EavStockItem CustomAttributeCategoryIds + + Pursuit Lumaflex&trade; Tone Band + x&trade; + 100 diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridSection.xml index 02bdbac313076..07dd26381fe08 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridSection.xml @@ -17,6 +17,7 @@ + diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontNavigationSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontNavigationSection.xml index c6bad0efb3ca7..0263e218c2417 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontNavigationSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontNavigationSection.xml @@ -12,5 +12,6 @@ + diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml index c814a886a2b33..990e488e9c662 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml @@ -63,4 +63,16 @@ + + + + + + + + + + + + From 65dbb0cf9575f4def1cf9caa1a0a2435a1d6fadf Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza Date: Wed, 27 Feb 2019 11:56:16 +0100 Subject: [PATCH 024/142] Extended tests coverage for more cases --- .../Magento/GraphQl/Quote/PlaceOrderTest.php | 163 ++++++++++++++++-- 1 file changed, 148 insertions(+), 15 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/PlaceOrderTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/PlaceOrderTest.php index 4871830e087ec..7d4358b79bdc4 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/PlaceOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/PlaceOrderTest.php @@ -7,7 +7,10 @@ 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; @@ -19,6 +22,11 @@ */ class PlaceOrderTest extends GraphQlAbstract { + /** + * @var ObjectManagerInterface + */ + private $objectManager; + /** * @var CustomerTokenServiceInterface */ @@ -41,11 +49,16 @@ class PlaceOrderTest extends GraphQlAbstract 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->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $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' + ); } /** @@ -54,14 +67,138 @@ protected function setUp() public function testPlaceOrder() { $reservedOrderId = 'test_order_1'; - $this->quoteResource->load( - $this->quote, - $reservedOrderId, - 'reserved_order_id' + + $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()); - $query =<<graphQlQuery($query, [], '', $this->getHeaderMap()); - - self::assertArrayHasKey('order_id', $response['placeOrder']['order']); - self::assertEquals($reservedOrderId, $response['placeOrder']['order']['order_id']); } /** * @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 { From b133eccf61ec7bbcf007233dd755109eb3a63ec7 Mon Sep 17 00:00:00 2001 From: Nikita Chubukov Date: Wed, 27 Feb 2019 17:23:38 +0300 Subject: [PATCH 025/142] MAGETWO-58219: Product Attribute Option Values for storeview instead of admin on product creation - Fix functional test --- .../Test/Mftf/Test/CreateProductAttributeEntityTest.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest.xml index 52022f32fd8ec..aa5fc05ad9db4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest.xml @@ -417,9 +417,9 @@ - - - - + + + + From e80b1620240c874cd29421299f1b9fb98617b606 Mon Sep 17 00:00:00 2001 From: Alexey Yakimovich Date: Thu, 28 Feb 2019 13:06:04 +0300 Subject: [PATCH 026/142] MAGETWO-70232: [GITHUB] Import customizable options adds it to another product if same SKU is filled#9457 - Fixed integration test related issue; --- app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php index 43d496c37ca69..5447c386c692c 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php @@ -58,9 +58,9 @@ public function execute($entity, $arguments = []) } } if ($options) { - $hasChangedSku = $entity->dataHasChangedFor('sku'); + $hasChangedSku = ($entity->getOrigData('sku') !== null && $entity->dataHasChangedFor('sku')); foreach ($options as $option) { - if ($hasChangedSku) { + if ($hasChangedSku && $option->hasData('product_sku')) { $option->setProductSku($entity->getSku()); } $this->optionRepository->save($option); From b8a1d21bf74dc3a3975acae37678e88313484b2b Mon Sep 17 00:00:00 2001 From: Mikalai Shostka Date: Thu, 28 Feb 2019 15:23:44 +0300 Subject: [PATCH 027/142] MAGETWO-58219: Product Attribute Option Values for storeview instead of admin on product creation - Fix functional test --- .../Mftf/Test/CreateProductAttributeEntityTest.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest.xml index aa5fc05ad9db4..d895993217e32 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest.xml @@ -262,10 +262,10 @@ - - - - + + + + @@ -333,8 +333,8 @@ - - + + From 1001a7cf7ec47286b56ac4d8e4b1971b4cf59700 Mon Sep 17 00:00:00 2001 From: Alexey Yakimovich Date: Thu, 28 Feb 2019 17:13:08 +0300 Subject: [PATCH 028/142] MAGETWO-70232: [GITHUB] Import customizable options adds it to another product if same SKU is filled#9457 - Fixed static test; --- .../Model/Product/Option/SaveHandler.php | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php index 5447c386c692c..715c7a7719079 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php @@ -59,14 +59,25 @@ public function execute($entity, $arguments = []) } if ($options) { $hasChangedSku = ($entity->getOrigData('sku') !== null && $entity->dataHasChangedFor('sku')); - foreach ($options as $option) { - if ($hasChangedSku && $option->hasData('product_sku')) { - $option->setProductSku($entity->getSku()); - } - $this->optionRepository->save($option); - } + $this->processOptionsSaving($options, $hasChangedSku, $entity->getSku()); } return $entity; } + + /** + * Save custom options + * + * @param array $options + * @param bool $hasChangedSku + * @param string $newSku + */ + private function processOptionsSaving($options, $hasChangedSku, $newSku) { + foreach ($options as $option) { + if ($hasChangedSku && $option->hasData('product_sku')) { + $option->setProductSku($newSku); + } + $this->optionRepository->save($option); + } + } } From 85829049bc98a795e7ede8ddac573567d09f533d Mon Sep 17 00:00:00 2001 From: Alexey Yakimovich Date: Thu, 28 Feb 2019 23:31:23 +0300 Subject: [PATCH 029/142] MAGETWO-70232: [GITHUB] Import customizable options adds it to another product if same SKU is filled#9457 - Fixed static test; --- app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php index 715c7a7719079..d210670920ef1 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php @@ -72,7 +72,8 @@ public function execute($entity, $arguments = []) * @param bool $hasChangedSku * @param string $newSku */ - private function processOptionsSaving($options, $hasChangedSku, $newSku) { + private function processOptionsSaving($options, $hasChangedSku, $newSku) + { foreach ($options as $option) { if ($hasChangedSku && $option->hasData('product_sku')) { $option->setProductSku($newSku); From af86cc601790cd362b2496bca8193d4a4f7ed9c5 Mon Sep 17 00:00:00 2001 From: Tyler Mills Date: Fri, 1 Mar 2019 10:44:15 -0500 Subject: [PATCH 030/142] Ensure `__toString()` catches all error types In PHP 7.1 `catch (\Exception ...)` does not catch fatal errors. Because this function can possibly throw fatal errors such as "`Call to a member function getRequestFieldName() on null`" which is an instance of `\Error`, we should catch `\Throwable` to ensure the exception makes it into the logger and `$result` is assigned the message. --- app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php index 9304d25cc8a98..d16b1eaad7f37 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php @@ -115,7 +115,7 @@ public function __toString() $this->compiler->compile($templateRootElement, $this->component, $this->component); $this->appendLayoutConfiguration(); $result = $this->compiler->postprocessing($this->template->__toString()); - } catch (\Exception $e) { + } catch (\Throwable $e) { $this->logger->critical($e->getMessage()); $result = $e->getMessage(); } From c80e1ba960c6a29e7ec3422c076330b7ffa117f9 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza Date: Sun, 3 Mar 2019 15:48:48 +0100 Subject: [PATCH 031/142] Added composer dependency (Sales module) --- app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php | 5 ----- app/code/Magento/QuoteGraphQl/composer.json | 3 ++- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php index cb5fcf0dad5ab..c087e867a342a 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php @@ -68,7 +68,6 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $orderId = $this->cartManagement->placeOrder($cart->getId()); $order = $this->orderRepository->get($orderId); - // TODO: populate with data return [ 'order' => [ 'order_id' => $order->getIncrementId() @@ -78,10 +77,6 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value throw new GraphQlInputException( __('Unable to place order: %message', ['message' => $exception->getMessage()]) ); - } catch (\Exception $exception) { - throw new GraphQlInputException( - __('Unable to place order. An internal error occurred') - ); } } } diff --git a/app/code/Magento/QuoteGraphQl/composer.json b/app/code/Magento/QuoteGraphQl/composer.json index 1bf4d581a5fe3..b53cab6656217 100644 --- a/app/code/Magento/QuoteGraphQl/composer.json +++ b/app/code/Magento/QuoteGraphQl/composer.json @@ -10,7 +10,8 @@ "magento/module-catalog": "*", "magento/module-store": "*", "magento/module-customer": "*", - "magento/module-customer-graph-ql": "*" + "magento/module-customer-graph-ql": "*", + "magento/module-sales" : "*" }, "suggest": { "magento/module-graph-ql": "*" From 17561929f9089b76afaff886c86c71693cf5918c Mon Sep 17 00:00:00 2001 From: Yuliya Labudova Date: Tue, 5 Mar 2019 10:47:09 +0300 Subject: [PATCH 032/142] MAGETWO-58226: Calendar Custom Options are displayed broken on Storefront if JS validation is performed - Fix functional test --- .../Magento/Catalog/Test/Block/Product/View/CustomOptions.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 dcc8cce970098..99ff9b73b92eb 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 @@ -128,7 +128,8 @@ class CustomOptions extends Form * * @var string */ - private $validationErrorMessage = '//div[@class="mage-error"][contains(text(), "required field")]'; + private $validationErrorMessage = '//div[@class="mage-error"][contains(text(), "required field")' . + 'and not(contains(@style,\'display\'))]'; /** * Get product options From 435d698ffd31c779eac0768f7aef5af24e8648df Mon Sep 17 00:00:00 2001 From: Alexey Yakimovich Date: Wed, 6 Mar 2019 15:17:34 +0300 Subject: [PATCH 033/142] MAGETWO-64838: Unable to create order from store front if customer address custom attribute is required. - Code refactoring; --- .../Magento/Customer/Controller/Address/File/Upload.php | 2 +- .../Webapi/CustomAttribute/PreprocessorInterface.php | 8 ++++---- .../Magento/Framework/Webapi/ServiceInputProcessor.php | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Address/File/Upload.php b/app/code/Magento/Customer/Controller/Address/File/Upload.php index dbbea482b0e52..adb4c7abd1729 100644 --- a/app/code/Magento/Customer/Controller/Address/File/Upload.php +++ b/app/code/Magento/Customer/Controller/Address/File/Upload.php @@ -91,6 +91,7 @@ public function execute() $result = $this->processError(($errorMessage)); } else { $result = $fileUploader->upload(); + $this->moveTmpFileToSuitableFolder($result); } } } catch (LocalizedException $e) { @@ -100,7 +101,6 @@ public function execute() $result = $this->processError($e->getMessage(), $e->getCode()); } - $this->moveTmpFileToSuitableFolder($result); /** @var \Magento\Framework\Controller\Result\Json $resultJson */ $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON); $resultJson->setData($result); diff --git a/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php b/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php index 0f8743f057601..26a13ebcc07b7 100644 --- a/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php +++ b/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php @@ -11,19 +11,19 @@ interface PreprocessorInterface { /** - * Check if this attribute data should be prepared + * Check if this attribute data should be processed * * @param string $key * @param mixed $attribute * @return bool */ - public function shouldBePrepared($key, $attribute); + public function shouldBeProcessed($key, $attribute); /** - * Prepare attribute object according to type rules + * Process attribute object according to type rules * * @param string $key * @param mixed $attribute */ - public function prepare($key, &$attribute); + public function process($key, &$attribute); } diff --git a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php index 616cbd6596522..45f2a8b931101 100644 --- a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php +++ b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php @@ -349,8 +349,8 @@ protected function convertCustomAttributeValue($customAttributesValueArray, $dat private function runCustomAttributePreprocessors($key, &$customAttribute) { foreach ($this->customAttributePreprocessors as $attributePreprocessor) { - if ($attributePreprocessor->shouldBePrepared($key, $customAttribute)) { - $attributePreprocessor->prepare($key, $customAttribute); + if ($attributePreprocessor->shouldBeProcessed($key, $customAttribute)) { + $attributePreprocessor->process($key, $customAttribute); } } } From 61f9a74d2a1f91cebeb09a1cde880b2c7287a4f4 Mon Sep 17 00:00:00 2001 From: Alexey Yakimovich Date: Wed, 6 Mar 2019 16:22:43 +0300 Subject: [PATCH 034/142] MAGETWO-70232: [GITHUB] Import customizable options adds it to another product if same SKU is filled#9457 - Fixed an issue with incorrect options saving on new created product; --- app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php index d210670920ef1..4d5dd57b76f61 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php @@ -58,8 +58,7 @@ public function execute($entity, $arguments = []) } } if ($options) { - $hasChangedSku = ($entity->getOrigData('sku') !== null && $entity->dataHasChangedFor('sku')); - $this->processOptionsSaving($options, $hasChangedSku, $entity->getSku()); + $this->processOptionsSaving($options, $entity->dataHasChangedFor('sku'), $entity->getSku()); } return $entity; From d583606dd48748d7ac6571e987c8b04cd8ae19e7 Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin Date: Wed, 6 Mar 2019 15:53:28 +0200 Subject: [PATCH 035/142] MAGETWO-96416: Clicking on a Root Category causes all other Root Categories to be expanded to the top-level categories --- app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php b/app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php index a67f55235b6df..479e212924f23 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php @@ -367,7 +367,7 @@ protected function _getNodeJson($node, $level = 0) } } - if ($isParent || $node->getLevel() < 2) { + if ($isParent || $node->getLevel() < 1) { $item['expanded'] = true; } From 3cf122cc0f0882b55a7fa92c465fdc04238c585a Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin Date: Thu, 7 Mar 2019 16:13:02 +0200 Subject: [PATCH 036/142] MAGETWO-96416: Clicking on a Root Category causes all other Root Categories to be expanded to the top-level categories --- .../Catalog/Block/Adminhtml/Category/Tree.php | 32 +++++++++++++++++-- .../Cms/Test/Mftf/Section/TinyMCESection.xml | 1 + ...WYSIWYGWithCatalogCategoryLinkTypeTest.xml | 1 + ...oWYSIWYGWithCatalogProductLinkTypeTest.xml | 1 + 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php b/app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php index 479e212924f23..83ec501592489 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php @@ -71,7 +71,7 @@ public function __construct( } /** - * @return void + * @inheritdoc */ protected function _construct() { @@ -80,7 +80,7 @@ protected function _construct() } /** - * @return $this + * @inheritdoc */ protected function _prepareLayout() { @@ -182,6 +182,8 @@ public function getSuggestedCategoriesJson($namePart) } /** + * Get add root button html + * * @return string */ public function getAddRootButtonHtml() @@ -190,6 +192,8 @@ public function getAddRootButtonHtml() } /** + * Get add sub button html + * * @return string */ public function getAddSubButtonHtml() @@ -198,6 +202,8 @@ public function getAddSubButtonHtml() } /** + * Get expand button html + * * @return string */ public function getExpandButtonHtml() @@ -206,6 +212,8 @@ public function getExpandButtonHtml() } /** + * Get collapse button html + * * @return string */ public function getCollapseButtonHtml() @@ -214,6 +222,8 @@ public function getCollapseButtonHtml() } /** + * Get store switcher + * * @return string */ public function getStoreSwitcherHtml() @@ -222,6 +232,8 @@ public function getStoreSwitcherHtml() } /** + * Get loader tree url + * * @param bool|null $expanded * @return string */ @@ -235,6 +247,8 @@ public function getLoadTreeUrl($expanded = null) } /** + * Get nodes url + * * @return string */ public function getNodesUrl() @@ -243,6 +257,8 @@ public function getNodesUrl() } /** + * Get switcher tree url + * * @return string */ public function getSwitchTreeUrl() @@ -254,6 +270,8 @@ public function getSwitchTreeUrl() } /** + * Get is was expanded + * * @return bool * @SuppressWarnings(PHPMD.BooleanGetMethodName) */ @@ -263,6 +281,8 @@ public function getIsWasExpanded() } /** + * Get move url + * * @return string */ public function getMoveUrl() @@ -271,6 +291,8 @@ public function getMoveUrl() } /** + * Get tree + * * @param mixed|null $parenNodeCategory * @return array */ @@ -282,6 +304,8 @@ public function getTree($parenNodeCategory = null) } /** + * Get tree json + * * @param mixed|null $parenNodeCategory * @return string */ @@ -390,6 +414,8 @@ public function buildNodeName($node) } /** + * Is category movable + * * @param Node|array $node * @return bool */ @@ -403,6 +429,8 @@ protected function _isCategoryMoveable($node) } /** + * Is parent selected category + * * @param Node|array $node * @return bool */ diff --git a/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml b/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml index ff6167ffc10e0..4fb008eb422d3 100644 --- a/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml +++ b/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml @@ -109,6 +109,7 @@ + diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml index 5b3679bed77e0..89f0439bd65b4 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml @@ -46,6 +46,7 @@ + diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml index 123d25f92b6b7..3b79770badca4 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml @@ -50,6 +50,7 @@ + From ef50e59c883fdb040d42053c34818205f0c22607 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz Date: Fri, 8 Mar 2019 11:42:22 +0000 Subject: [PATCH 037/142] MFTF / Remove redundant ActionGroups --- ...oreFrontPasswordAutocompleteOffActionGroup.xml | 14 -------------- .../StoreFrontClickSignInButtonActionGroup.xml | 15 --------------- 2 files changed, 29 deletions(-) delete mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStoreFrontPasswordAutocompleteOffActionGroup.xml delete mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StoreFrontClickSignInButtonActionGroup.xml diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStoreFrontPasswordAutocompleteOffActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStoreFrontPasswordAutocompleteOffActionGroup.xml deleted file mode 100644 index 23a067cd94eea..0000000000000 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStoreFrontPasswordAutocompleteOffActionGroup.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StoreFrontClickSignInButtonActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StoreFrontClickSignInButtonActionGroup.xml deleted file mode 100644 index b12858fc1037e..0000000000000 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StoreFrontClickSignInButtonActionGroup.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - From c5d1d62e10b3e024bd3d4295745a4440b062f9a7 Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin Date: Mon, 11 Mar 2019 11:31:28 +0200 Subject: [PATCH 038/142] MAGETWO-96416: Clicking on a Root Category causes all other Root Categories to be expanded to the top-level categories --- .../Test/Mftf/Section/AdminCategorySidebarTreeSection.xml | 1 + app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml | 1 - ...dminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml | 5 +++-- ...AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml index 14e714cb2b6b7..fba28b3feaff1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml @@ -16,5 +16,6 @@ + diff --git a/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml b/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml index 4fb008eb422d3..ff6167ffc10e0 100644 --- a/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml +++ b/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml @@ -109,7 +109,6 @@ - diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml index 89f0439bd65b4..393e25e474f12 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml @@ -46,8 +46,9 @@ - - + + + diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml index 3b79770badca4..9ee9d27de477a 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml @@ -50,7 +50,8 @@ - + + From ace7f4c3f568e8dee4c6b1d6f9d06428368d53e2 Mon Sep 17 00:00:00 2001 From: Nikita Chubukov Date: Mon, 11 Mar 2019 13:59:54 +0300 Subject: [PATCH 039/142] MAGETWO-58219: Product Attribute Option Values for storeview instead of admin on product creation - Removed area check in data provider --- .../DataProvider/Product/Form/Modifier/Eav.php | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index c96fe54a87620..8326c3b531892 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -35,7 +35,6 @@ use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav\CompositeConfigProcessor; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Eav\Model\ResourceModel\Entity\Attribute\CollectionFactory as AttributeCollectionFactory; -use Magento\Framework\App\State; /** * Class Eav @@ -214,11 +213,6 @@ class Eav extends AbstractModifier */ private $scopeConfig; - /** - * @var State - */ - private $state; - /** * Eav constructor. * @param LocatorInterface $locator @@ -243,7 +237,6 @@ class Eav extends AbstractModifier * @param CompositeConfigProcessor|null $wysiwygConfigProcessor * @param ScopeConfigInterface|null $scopeConfig * @param AttributeCollectionFactory $attributeCollectionFactory - * @param State $state * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -268,8 +261,7 @@ public function __construct( $attributesToEliminate = [], CompositeConfigProcessor $wysiwygConfigProcessor = null, ScopeConfigInterface $scopeConfig = null, - AttributeCollectionFactory $attributeCollectionFactory = null, - State $state = null + AttributeCollectionFactory $attributeCollectionFactory = null ) { $this->locator = $locator; $this->catalogEavValidationRules = $catalogEavValidationRules; @@ -296,8 +288,6 @@ public function __construct( ->get(ScopeConfigInterface::class); $this->attributeCollectionFactory = $attributeCollectionFactory ?: \Magento\Framework\App\ObjectManager::getInstance()->get(AttributeCollectionFactory::class); - $this->state = $state ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(State::class); } /** @@ -686,9 +676,7 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC // TODO: Refactor to $attribute->getOptions() when MAGETWO-48289 is done $attributeModel = $this->getAttributeModel($attribute); if ($attributeModel->usesSource()) { - $options = ($this->state->getAreaCode() == \Magento\Framework\App\Area::AREA_ADMINHTML) - ? $attributeModel->getSource()->getAllOptions(true, true) - : $attributeModel->getSource()->getAllOptions(); + $options = $attributeModel->getSource()->getAllOptions(true, true); $meta = $this->arrayManager->merge($configPath, $meta, [ 'options' => $this->convertOptionsValueToString($options), ]); From 034a86293611956dd2e3ae90a44817755a247076 Mon Sep 17 00:00:00 2001 From: Alexey Yakimovich Date: Mon, 11 Mar 2019 17:27:57 +0300 Subject: [PATCH 040/142] MAGETWO-64838: Unable to create order from store front if customer address custom attribute is required. - Added additial checks before call attribute preprocessors; --- .../CustomAttribute/PreprocessorInterface.php | 7 ++++ .../Webapi/ServiceInputProcessor.php | 34 +++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php b/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php index 26a13ebcc07b7..820936abd49ba 100644 --- a/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php +++ b/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php @@ -26,4 +26,11 @@ public function shouldBeProcessed($key, $attribute); * @param mixed $attribute */ public function process($key, &$attribute); + + /** + * Get list of affected attributes for the current preprocessor + * + * @return array + */ + public function getAffectedAttributes(); } diff --git a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php index 45f2a8b931101..a116e0be8649f 100644 --- a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php +++ b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php @@ -78,6 +78,11 @@ class ServiceInputProcessor implements ServicePayloadConverterInterface */ private $customAttributePreprocessors; + /** + * @var array + */ + private $attributesPreprocessorsMap = []; + /** * Initialize dependencies. * @@ -296,9 +301,12 @@ protected function convertCustomAttributeValue($customAttributesValueArray, $dat { $result = []; $dataObjectClassName = ltrim($dataObjectClassName, '\\'); + $attributesPreprocessorMap = $this->getAttributesPreprocessorsMap(); foreach ($customAttributesValueArray as $key => $customAttribute) { - $this->runCustomAttributePreprocessors($key, $customAttribute); + if($key && is_array($customAttribute) && array_key_exists($key, $attributesPreprocessorMap)) { + $this->runCustomAttributePreprocessors($key, $customAttribute, $attributesPreprocessorMap[$key]); + } if (!is_array($customAttribute)) { $customAttribute = [AttributeValue::ATTRIBUTE_CODE => $key, AttributeValue::VALUE => $customAttribute]; } @@ -339,6 +347,24 @@ protected function convertCustomAttributeValue($customAttributesValueArray, $dat return $result; } + /** + * Get map of preprocessors related to the custom attributes + * + * @return array + */ + private function getAttributesPreprocessorsMap() + { + if (!$this->attributesPreprocessorsMap) { + foreach ($this->customAttributePreprocessors as $attributePreprocessor) { + foreach ($attributePreprocessor->getAffectedAttributes() as $attributeKey) { + $this->attributesPreprocessorsMap[$attributeKey][] = get_class($attributePreprocessor); + } + } + } + + return $this->attributesPreprocessorsMap; + } + /** * Prepare attribute value by loaded attribute preprocessors * @@ -346,10 +372,12 @@ protected function convertCustomAttributeValue($customAttributesValueArray, $dat * @param mixed $customAttribute * @return bool */ - private function runCustomAttributePreprocessors($key, &$customAttribute) + private function runCustomAttributePreprocessors($key, &$customAttribute, $preprocessorlsList) { foreach ($this->customAttributePreprocessors as $attributePreprocessor) { - if ($attributePreprocessor->shouldBeProcessed($key, $customAttribute)) { + if (array_key_exists(get_class($attributePreprocessor), $preprocessorlsList) + && $attributePreprocessor->shouldBeProcessed($key, $customAttribute) + ) { $attributePreprocessor->process($key, $customAttribute); } } From 0408d5f7afc2713eb8be54e7dab2be6148990e09 Mon Sep 17 00:00:00 2001 From: Alexey Yakimovich Date: Mon, 11 Mar 2019 17:49:55 +0300 Subject: [PATCH 041/142] MAGETWO-64838: Unable to create order from store front if customer address custom attribute is required. - code refactoring; --- .../Magento/Framework/Webapi/ServiceInputProcessor.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php index a116e0be8649f..d6d70eeec1eb6 100644 --- a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php +++ b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php @@ -357,7 +357,7 @@ private function getAttributesPreprocessorsMap() if (!$this->attributesPreprocessorsMap) { foreach ($this->customAttributePreprocessors as $attributePreprocessor) { foreach ($attributePreprocessor->getAffectedAttributes() as $attributeKey) { - $this->attributesPreprocessorsMap[$attributeKey][] = get_class($attributePreprocessor); + $this->attributesPreprocessorsMap[$attributeKey][] = $attributePreprocessor; } } } @@ -374,10 +374,8 @@ private function getAttributesPreprocessorsMap() */ private function runCustomAttributePreprocessors($key, &$customAttribute, $preprocessorlsList) { - foreach ($this->customAttributePreprocessors as $attributePreprocessor) { - if (array_key_exists(get_class($attributePreprocessor), $preprocessorlsList) - && $attributePreprocessor->shouldBeProcessed($key, $customAttribute) - ) { + foreach ($preprocessorlsList as $attributePreprocessor) { + if ($attributePreprocessor->shouldBeProcessed($key, $customAttribute)) { $attributePreprocessor->process($key, $customAttribute); } } From 06693faebc22a9c62f53dac54e51634ad1f8f3d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= Date: Mon, 11 Mar 2019 23:13:10 +0100 Subject: [PATCH 042/142] Fix AdminChangeProductAttributeSet test --- .../Catalog/Test/Mftf/Test/AdminChangeProductAttributeSet.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeProductAttributeSet.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeProductAttributeSet.xml index 3027416ee520b..bcfab6ccfdf1f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeProductAttributeSet.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeProductAttributeSet.xml @@ -34,7 +34,7 @@ - + From 7df1f1690fefb72e36d91808921c9912efa3a703 Mon Sep 17 00:00:00 2001 From: Alexey Yakimovich Date: Tue, 12 Mar 2019 14:57:57 +0300 Subject: [PATCH 043/142] MAGETWO-64838: Unable to create order from store front if customer address custom attribute is required - Fixed static tests; --- .../Framework/Webapi/ServiceInputProcessor.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php index d6d70eeec1eb6..96f06e93a0411 100644 --- a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php +++ b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php @@ -301,12 +301,9 @@ protected function convertCustomAttributeValue($customAttributesValueArray, $dat { $result = []; $dataObjectClassName = ltrim($dataObjectClassName, '\\'); - $attributesPreprocessorMap = $this->getAttributesPreprocessorsMap(); foreach ($customAttributesValueArray as $key => $customAttribute) { - if($key && is_array($customAttribute) && array_key_exists($key, $attributesPreprocessorMap)) { - $this->runCustomAttributePreprocessors($key, $customAttribute, $attributesPreprocessorMap[$key]); - } + $this->runCustomAttributePreprocessors($key, $customAttribute); if (!is_array($customAttribute)) { $customAttribute = [AttributeValue::ATTRIBUTE_CODE => $key, AttributeValue::VALUE => $customAttribute]; } @@ -370,13 +367,16 @@ private function getAttributesPreprocessorsMap() * * @param string $key * @param mixed $customAttribute - * @return bool */ - private function runCustomAttributePreprocessors($key, &$customAttribute, $preprocessorlsList) + private function runCustomAttributePreprocessors($key, &$customAttribute) { - foreach ($preprocessorlsList as $attributePreprocessor) { - if ($attributePreprocessor->shouldBeProcessed($key, $customAttribute)) { - $attributePreprocessor->process($key, $customAttribute); + $preprocessorsMap = $this->getAttributesPreprocessorsMap(); + if ($key && is_array($customAttribute) && array_key_exists($key, $preprocessorsMap)) { + $preprocessorsList = $preprocessorsMap[$key]; + foreach ($preprocessorsList as $attributePreprocessor) { + if ($attributePreprocessor->shouldBeProcessed($key, $customAttribute)) { + $attributePreprocessor->process($key, $customAttribute); + } } } } From 8029be3355c3cb1dbebd185de54583a6e27f3c65 Mon Sep 17 00:00:00 2001 From: Michael Lehmkuhl Date: Thu, 14 Mar 2019 14:40:57 -0500 Subject: [PATCH 044/142] Fixes nested array for used products cache key When $requiredAttributeIds is passed as an array, it was previously being added to the $keyParts array directly, which resulted in a nested array. When this nested array is passed to getUsedProductsCacheKey(), the implode() in that function throws a notice and produces a cache key that contains the non-unique string "Array" as a part. This can result in caching errors where simple children of configurable products are concerned (e.g., swatches). --- .../Model/Product/Type/Configurable.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php index 46f10608bc95e..47c1a3c39f9a8 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php @@ -1232,6 +1232,8 @@ public function isPossibleBuyFromList($product) /** * Returns array of sub-products for specified configurable product * + * $requiredAttributeIds - one dimensional array, if provided + * * Result array contains all children for specified configurable product * * @param \Magento\Catalog\Model\Product $product @@ -1245,9 +1247,12 @@ public function getUsedProducts($product, $requiredAttributeIds = null) __METHOD__, $product->getData($metadata->getLinkField()), $product->getStoreId(), - $this->getCustomerSession()->getCustomerGroupId(), - $requiredAttributeIds + $this->getCustomerSession()->getCustomerGroupId() ]; + if (!is_null($requiredAttributeIds)) { + sort($requiredAttributeIds); + $keyParts[] = implode('', $requiredAttributeIds); + } $cacheKey = $this->getUsedProductsCacheKey($keyParts); return $this->loadUsedProducts($product, $cacheKey); } From b3280d0b0b740d389928618584650bba19309731 Mon Sep 17 00:00:00 2001 From: Vasilii Date: Sat, 16 Mar 2019 11:45:47 +0200 Subject: [PATCH 045/142] magento/graphql-ce:#468 - Resolve coupling between objects in `\Magento\QuoteGraphQl\Model\Cart\SetBillingAddressOnCart` --- .../CreateQuoteAddressByCustomerAddress.php | 78 +++++++++++++++++++ .../Model/Cart/SetBillingAddressOnCart.php | 50 ++++-------- 2 files changed, 95 insertions(+), 33 deletions(-) create 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 new file mode 100644 index 0000000000000..2e2588ea81068 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateQuoteAddressByCustomerAddress.php @@ -0,0 +1,78 @@ +quoteAddressFactory = $quoteAddressFactory; + $this->getCustomer = $getCustomer; + $this->getCustomerAddress = $getCustomerAddress; + } + + /** + * @param ContextInterface $context + * @param int|string|null $customerAddressId + * @param array|null $customerAddress + * @return Address + * @throws GraphQlAuthenticationException + * @throws GraphQlAuthorizationException + * @throws GraphQlInputException + * @throws GraphQlNoSuchEntityException + */ + 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/SetBillingAddressOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php index 31524ea023222..65afbecb2c3f5 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php @@ -7,8 +7,8 @@ namespace Magento\QuoteGraphQl\Model\Cart; -use Magento\CustomerGraphQl\Model\Customer\Address\GetCustomerAddress; -use Magento\CustomerGraphQl\Model\Customer\GetCustomer; +use Magento\Framework\GraphQl\Exception\GraphQlAuthenticationException; +use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; @@ -20,41 +20,25 @@ class SetBillingAddressOnCart { /** - * @var QuoteAddressFactory - */ - private $quoteAddressFactory; - - /** - * @var GetCustomer - */ - private $getCustomer; - - /** - * @var GetCustomerAddress + * @var AssignBillingAddressToCart */ - private $getCustomerAddress; + private $assignBillingAddressToCart; /** - * @var AssignBillingAddressToCart + * @var CreateQuoteAddressByCustomerAddress */ - private $assignBillingAddressToCart; + private $createQuoteAddressByCustomerAddress; /** - * @param QuoteAddressFactory $quoteAddressFactory - * @param GetCustomer $getCustomer - * @param GetCustomerAddress $getCustomerAddress * @param AssignBillingAddressToCart $assignBillingAddressToCart + * @param CreateQuoteAddressByCustomerAddress $createQuoteAddressByCustomerAddress */ public function __construct( - QuoteAddressFactory $quoteAddressFactory, - GetCustomer $getCustomer, - GetCustomerAddress $getCustomerAddress, - AssignBillingAddressToCart $assignBillingAddressToCart + AssignBillingAddressToCart $assignBillingAddressToCart, + CreateQuoteAddressByCustomerAddress $createQuoteAddressByCustomerAddress ) { - $this->quoteAddressFactory = $quoteAddressFactory; - $this->getCustomer = $getCustomer; - $this->getCustomerAddress = $getCustomerAddress; $this->assignBillingAddressToCart = $assignBillingAddressToCart; + $this->createQuoteAddressByCustomerAddress = $createQuoteAddressByCustomerAddress; } /** @@ -66,6 +50,8 @@ public function __construct( * @return void * @throws GraphQlInputException * @throws GraphQlNoSuchEntityException + * @throws GraphQlAuthorizationException + * @throws GraphQlAuthenticationException */ public function execute(ContextInterface $context, CartInterface $cart, array $billingAddressInput): void { @@ -93,13 +79,11 @@ public function execute(ContextInterface $context, CartInterface $cart, array $b ); } - if (null === $customerAddressId) { - $billingAddress = $this->quoteAddressFactory->createBasedOnInputData($addressInput); - } else { - $customer = $this->getCustomer->execute($context); - $customerAddress = $this->getCustomerAddress->execute((int)$customerAddressId, (int)$customer->getId()); - $billingAddress = $this->quoteAddressFactory->createBasedOnCustomerAddress($customerAddress); - } + $billingAddress = $this->createQuoteAddressByCustomerAddress->execute( + $context, + $customerAddressId, + $addressInput + ); $this->assignBillingAddressToCart->execute($cart, $billingAddress, $useForShipping); } From b93da7a4b8c1e0df65ca505dbdc47be2ed8d3d2c Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Sat, 16 Mar 2019 23:44:21 +0200 Subject: [PATCH 046/142] #481 Created a webapi test for removing coupon from the guest quote --- .../Quote/Guest/RemoveCouponFromCartTest.php | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveCouponFromCartTest.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 new file mode 100644 index 0000000000000..45b2ff8313e41 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveCouponFromCartTest.php @@ -0,0 +1,143 @@ +quoteResource = $objectManager->create(QuoteResource::class); + $this->quote = $objectManager->create(Quote::class); + $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 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); + + /* Remove coupon from quote */ + $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); + $response = $this->graphQlQuery($query); + + self::assertArrayHasKey('removeCouponFromCart', $response); + self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); + } + + /** + * @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 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'; + + /* Remove coupon from quote */ + $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); + + self::expectExceptionMessage('Could not find a cart with ID "' . $maskedQuoteId. '"'); + $this->graphQlQuery($query); + } + + /** + * @param string $maskedQuoteId + * @param string $couponCode + * @return string + */ + private function prepareAddCouponRequestQuery(string $maskedQuoteId, string $couponCode): string + { + return << Date: Sat, 16 Mar 2019 23:45:24 +0200 Subject: [PATCH 047/142] #481 Removed extracted code from the test --- .../Magento/GraphQl/Quote/CouponTest.php | 77 ------------------- 1 file changed, 77 deletions(-) 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 54fdc3ac0f360..d24c3d6e78340 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/CouponTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/CouponTest.php @@ -126,63 +126,6 @@ public function testGuestCustomerAttemptToChangeCustomerCart() $this->graphQlQuery($query); } - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php - */ - public function testRemoveCoupon() - { - $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()); - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); - $this->graphQlQuery($query); - - /* Remove coupon from quote */ - $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); - $response = $this->graphQlQuery($query); - - self::assertArrayHasKey('removeCouponFromCart', $response); - self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); - } - - /** - * @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 testRemoveCouponFromCustomerCartByGuest() - { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $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); - } - /** * @param string $maskedQuoteId * @param string $couponCode @@ -200,26 +143,6 @@ private function prepareAddCouponRequestQuery(string $maskedQuoteId, string $cou } } } -QUERY; - } - - /** - * @param string $maskedQuoteId - * @return string - */ - private function prepareRemoveCouponRequestQuery(string $maskedQuoteId): string - { - return << Date: Sun, 17 Mar 2019 00:04:38 +0200 Subject: [PATCH 048/142] #481 Added a wapapi test to cover removeCouponFromCart case --- .../Customer/RemoveCouponFromCartTest.php | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveCouponFromCartTest.php 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 new file mode 100644 index 0000000000000..51eac60d45282 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveCouponFromCartTest.php @@ -0,0 +1,142 @@ +quoteResource = $objectManager->create(QuoteResource::class); + $this->quote = $objectManager->create(Quote::class); + $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::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 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()); + + $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); + + /* Remove coupon from quote */ + $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $queryHeaders); + + self::assertArrayHasKey('removeCouponFromCart', $response); + self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); + } + + /** + * 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]; + } + + /** + * Retrieve add coupon GraphQL query + * + * @param string $maskedQuoteId + * @param string $couponCode + * @return string + */ + private function prepareAddCouponRequestQuery(string $maskedQuoteId, string $couponCode): string + { + return << Date: Sun, 17 Mar 2019 13:30:56 +0200 Subject: [PATCH 049/142] #481 Added testRemoveCouponFromAonotherCustomerCart and testRemoveCouponFromGuestCart --- .../Customer/RemoveCouponFromCartTest.php | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) 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 51eac60d45282..f9cba5526b864 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 @@ -81,6 +81,66 @@ public function testRemoveCouponFromCart() 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 testRemoveCouponFromAonotherCustomerCart() + { + $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()); + + $this->quote->setCustomerId(1); + $this->quoteResource->save($this->quote); + + $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); + $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); + $this->graphQlQuery($query, [], '', $queryHeaders); + + /* Remove coupon from quote */ + $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); + } + + /** + * @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 testRemoveCouponFromGuestCart() + { + $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); + + /* 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); + } + /** * Retrieve customer authorization headers * From d7a53792d6df758da54dc3c12698df1ca59b35bb Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Sun, 17 Mar 2019 13:34:34 +0200 Subject: [PATCH 050/142] #481 Added comments --- .../Quote/Customer/RemoveCouponFromCartTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 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 f9cba5526b864..cba25e0c40e39 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 @@ -58,7 +58,7 @@ public function testRemoveCouponFromCart() { $couponCode = '2?ds5!2d'; - /* Apply coupon to the quote */ + /* Apply coupon to the customer quote */ $this->quoteResource->load( $this->quote, 'test_order_with_simple_product_without_address', @@ -73,7 +73,7 @@ public function testRemoveCouponFromCart() $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); $this->graphQlQuery($query, [], '', $queryHeaders); - /* Remove coupon from quote */ + /* Remove coupon from the quote */ $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); $response = $this->graphQlQuery($query, [], '', $queryHeaders); @@ -90,7 +90,7 @@ public function testRemoveCouponFromAonotherCustomerCart() { $couponCode = '2?ds5!2d'; - /* Apply coupon to the quote */ + /* Apply coupon to the first customer quote */ $this->quoteResource->load( $this->quote, 'test_order_with_simple_product_without_address', @@ -105,7 +105,7 @@ public function testRemoveCouponFromAonotherCustomerCart() $queryHeaders = $this->prepareAuthorizationHeaders('customer@example.com', 'password'); $this->graphQlQuery($query, [], '', $queryHeaders); - /* Remove coupon from quote */ + /* Remove coupon from the quote from the second customer */ $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); $queryHeaders = $this->prepareAuthorizationHeaders('customer_two@example.com', 'password'); @@ -122,7 +122,7 @@ public function testRemoveCouponFromGuestCart() { $couponCode = '2?ds5!2d'; - /* Apply coupon to the quote */ + /* Apply coupon to the guest quote */ $this->quoteResource->load( $this->quote, 'test_order_with_simple_product_without_address', @@ -136,7 +136,7 @@ public function testRemoveCouponFromGuestCart() /* 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); } From 9000000a7cad2bbd8ddb320bfcf643a92e8cd1c9 Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Sun, 17 Mar 2019 14:34:14 +0200 Subject: [PATCH 051/142] #481 Added more test cases covered --- .../Customer/RemoveCouponFromCartTest.php | 178 +++++++++++++++++- 1 file changed, 176 insertions(+), 2 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 cba25e0c40e39..818af4c8853ec 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 @@ -8,10 +8,14 @@ namespace Magento\GraphQl\Quote\Customer; use Magento\Framework\Exception\AuthenticationException; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\NoSuchEntityException; 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; @@ -40,6 +44,16 @@ class RemoveCouponFromCartTest extends GraphQlAbstract */ private $customerTokenService; + /** + * @var CouponRepositoryInterface + */ + private $couponRepository; + + /** + * @var Coupon + */ + private $coupon; + protected function setUp() { $objectManager = Bootstrap::getObjectManager(); @@ -47,6 +61,8 @@ protected function setUp() $this->quote = $objectManager->create(Quote::class); $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->couponRepository = $objectManager->get(CouponRepositoryInterface::class); + $this->coupon = $objectManager->create(Coupon::class); } /** @@ -81,16 +97,119 @@ public function testRemoveCouponFromCart() self::assertNull($response['removeCouponFromCart']['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 + */ + public function testRemoveCouponFromCartTwice() + { + $couponCode = '2?ds5!2d'; + + /* Apply coupon to the customer quote */ + $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); + + /* 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']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + */ + 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); + + $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); + } + + /** + * @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 testRemoveCouponFromCartWithoutItems() + { + $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 */ + $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); + + 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 testRemoveCouponFromAonotherCustomerCart() + public function testRemoveCouponFromAnotherCustomerCart() { $couponCode = '2?ds5!2d'; - /* Apply coupon to the first customer quote */ + /* Assign the quote to the customer */ $this->quoteResource->load( $this->quote, 'test_order_with_simple_product_without_address', @@ -101,6 +220,7 @@ public function testRemoveCouponFromAonotherCustomerCart() $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); @@ -141,6 +261,60 @@ public function testRemoveCouponFromGuestCart() $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); + + /* 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']); + } + + /** + * 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); + } + } + /** * Retrieve customer authorization headers * From a8b4cc992eda5ec163676e3699630e0e5d5144a0 Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Sun, 17 Mar 2019 14:38:37 +0200 Subject: [PATCH 052/142] #481 Added testRemoveCouponFromCartWithNoCouponApplied case --- .../Customer/RemoveCouponFromCartTest.php | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 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 818af4c8853ec..b228d315f8890 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 @@ -74,7 +74,7 @@ public function testRemoveCouponFromCart() { $couponCode = '2?ds5!2d'; - /* Apply coupon to the customer quote */ + /* Assign the quote to the customer */ $this->quoteResource->load( $this->quote, 'test_order_with_simple_product_without_address', @@ -85,6 +85,7 @@ public function testRemoveCouponFromCart() $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); @@ -106,7 +107,7 @@ public function testRemoveCouponFromCartTwice() { $couponCode = '2?ds5!2d'; - /* Apply coupon to the customer quote */ + /* Assign the quote to the customer */ $this->quoteResource->load( $this->quote, 'test_order_with_simple_product_without_address', @@ -117,6 +118,7 @@ public function testRemoveCouponFromCartTwice() $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); @@ -136,6 +138,32 @@ public function testRemoveCouponFromCartTwice() self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); } + /** + * @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 From 7677da6c9f1597ba5e92a9fdd3360cbd97da1c61 Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Sun, 17 Mar 2019 14:47:38 +0200 Subject: [PATCH 053/142] #481 Added cases to the guest coupon test --- .../Quote/Guest/RemoveCouponFromCartTest.php | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) 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 45b2ff8313e41..c5929795b534a 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,9 +7,13 @@ 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\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -33,12 +37,24 @@ class RemoveCouponFromCartTest extends GraphQlAbstract */ 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); } /** @@ -102,6 +118,106 @@ public function testRemoveCouponFromNonExistentCart() $this->graphQlQuery($query); } + /** + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + */ + 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); + + $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 + */ + public function testRemoveCouponFromCartWithoutItems() + { + $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); + + /* Remove coupon from the guest quote */ + $query = $this->prepareRemoveCouponRequestQuery($maskedQuoteId); + $response = $this->graphQlQuery($query); + + self::assertArrayHasKey('removeCouponFromCart', $response); + self::assertNull($response['removeCouponFromCart']['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 testRemoveNonExistentCouponFromCart() + { + $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); + + /* 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 From 2ce4ab0ffcd5d7f791c28f543037ff7f31bc7bdf Mon Sep 17 00:00:00 2001 From: Graham Wharton Date: Mon, 18 Mar 2019 12:11:30 +0000 Subject: [PATCH 054/142] Moved generation of Gallery options and Gallery fullscreen options to own block functions. --- .../Block/Product/View/GalleryOptions.php | 152 ++++++++++ .../Block/Product/View/GalleryOptionsTest.php | 275 ++++++++++++++++++ .../frontend/layout/catalog_product_view.xml | 6 +- .../templates/product/view/gallery.phtml | 40 +-- 4 files changed, 434 insertions(+), 39 deletions(-) create mode 100644 app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php create mode 100644 app/code/Magento/Catalog/Test/Unit/Block/Product/View/GalleryOptionsTest.php diff --git a/app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php b/app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php new file mode 100644 index 0000000000000..084da345a12d4 --- /dev/null +++ b/app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php @@ -0,0 +1,152 @@ +gallery = $gallery; + $this->jsonSerializer = $jsonSerializer; + parent::__construct($context, $arrayUtils, $data); + } + + /** + * Retrieve gallery options in JSON format + * + * @return string + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function getOptionsJson() + { + $optionItems = null; + + //Special case for gallery/nav which can be the string "thumbs/false/dots" + if (is_bool($this->getVar("gallery/nav"))) { + $optionItems['nav'] = $this->getVar("gallery/nav") ? 'true' : 'false'; + } else { + $optionItems['nav'] = $this->escapeHtml($this->getVar("gallery/nav")); + } + + $optionItems['loop'] = $this->getVar("gallery/loop"); + $optionItems['keyboard'] = $this->getVar("gallery/keyboard"); + $optionItems['arrows'] = $this->getVar("gallery/arrows"); + $optionItems['allowfullscreen'] = $this->getVar("gallery/allowfullscreen"); + $optionItems['showCaption'] = $this->getVar("gallery/caption"); + $optionItems['width'] = (int)$this->escapeHtml( + $this->gallery->getImageAttribute('product_page_image_medium', 'width') + ); + $optionItems['thumbwidth'] = (int)$this->escapeHtml( + $this->gallery->getImageAttribute('product_page_image_small', 'width') + ); + + if ($this->gallery->getImageAttribute('product_page_image_small', 'height') || + $this->gallery->getImageAttribute('product_page_image_small', 'width')) { + $optionItems['thumbheight'] = (int)$this->escapeHtml( + $this->gallery->getImageAttribute('product_page_image_small', 'height') ?: + $this->gallery->getImageAttribute('product_page_image_small', 'width') + ); + } + + if ($this->gallery->getImageAttribute('product_page_image_medium', 'height') || + $this->gallery->getImageAttribute('product_page_image_medium', 'width')) { + $optionItems['height'] = (int)$this->escapeHtml( + $this->gallery->getImageAttribute('product_page_image_medium', 'height') ?: + $this->gallery->getImageAttribute('product_page_image_medium', 'width') + ); + } + + if ($this->getVar("gallery/transition/duration")) { + $optionItems['transitionduration'] = + (int)$this->escapeHtml($this->getVar("gallery/transition/duration")); + } + + $optionItems['transition'] = $this->escapeHtml($this->getVar("gallery/transition/effect")); + $optionItems['navarrows'] = $this->getVar("gallery/navarrows"); + $optionItems['navtype'] = $this->escapeHtml($this->getVar("gallery/navtype")); + $optionItems['navdir'] = $this->escapeHtml($this->getVar("gallery/navdir")); + + if ($this->getVar("gallery/thumbmargin")) { + $optionItems['thumbmargin'] = (int)$this->escapeHtml($this->getVar("gallery/thumbmargin")); + } + + return $this->jsonSerializer->serialize($optionItems); + } + + /** + * Retrieve gallery fullscreen options in JSON format + * + * @return string + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function getFSOptionsJson() + { + $fsOptionItems = null; + + //Special case for gallery/nav which can be the string "thumbs/false/dots" + if (is_bool($this->getVar("gallery/fullscreen/nav"))) { + $fsOptionItems['nav'] = $this->getVar("gallery/fullscreen/nav") ? 'true' : 'false'; + } else { + $fsOptionItems['nav'] = $this->escapeHtml($this->getVar("gallery/fullscreen/nav")); + } + + $fsOptionItems['loop'] = $this->getVar("gallery/fullscreen/loop"); + $fsOptionItems['navdir'] = $this->escapeHtml($this->getVar("gallery/fullscreen/navdir")); + $fsOptionItems['navarrows'] = $this->getVar("gallery/fullscreen/navarrows"); + $fsOptionItems['navtype'] = $this->escapeHtml($this->getVar("gallery/fullscreen/navtype")); + $fsOptionItems['arrows'] = $this->getVar("gallery/fullscreen/arrows"); + $fsOptionItems['showCaption'] = $this->getVar("gallery/fullscreen/caption"); + + if ($this->getVar("gallery/fullscreen/transition/duration")) { + $fsOptionItems['transitionduration'] = (int)$this->escapeHtml( + $this->getVar("gallery/fullscreen/transition/duration") + ); + } + + $fsOptionItems['transition'] = $this->escapeHtml($this->getVar("gallery/fullscreen/transition/effect")); + + if ($this->getVar("gallery/fullscreen/keyboard")) { + $fsOptionItems['keyboard'] = $this->getVar("gallery/fullscreen/keyboard"); + } + + if ($this->getVar("gallery/fullscreen/thumbmargin")) { + $fsOptionItems['thumbmargin'] = + (int)$this->escapeHtml($this->getVar("gallery/fullscreen/thumbmargin")); + } + + return $this->jsonSerializer->serialize($fsOptionItems); + } +} 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 new file mode 100644 index 0000000000000..3a5b96ec53267 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/View/GalleryOptionsTest.php @@ -0,0 +1,275 @@ +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->assertInternalType("string", $decodedJson['nav']); + + $this->assertSame(false, $decodedJson['loop']); + $this->assertInternalType("bool", $decodedJson['loop']); + + $this->assertSame(true, $decodedJson['keyboard']); + $this->assertInternalType("bool", $decodedJson['keyboard']); + + $this->assertSame(true, $decodedJson['arrows']); + $this->assertInternalType("bool", $decodedJson['arrows']); + + $this->assertSame(false, $decodedJson['showCaption']); + $this->assertInternalType("bool", $decodedJson['showCaption']); + + $this->assertSame(true, $decodedJson['allowfullscreen']); + $this->assertInternalType("bool", $decodedJson['allowfullscreen']); + + $this->assertSame('horizontal', $decodedJson['navdir']); + $this->assertInternalType("string", $decodedJson['navdir']); + + $this->assertSame(true, $decodedJson['navarrows']); + $this->assertInternalType("bool", $decodedJson['navarrows']); + + $this->assertSame('slides', $decodedJson['navtype']); + $this->assertInternalType("string", $decodedJson['navtype']); + + $this->assertSame(5, $decodedJson['thumbmargin']); + $this->assertInternalType("int", $decodedJson['thumbmargin']); + + $this->assertSame('slide', $decodedJson['transition']); + $this->assertInternalType("string", $decodedJson['transition']); + + $this->assertSame(500, $decodedJson['transitionduration']); + $this->assertInternalType("int", $decodedJson['transitionduration']); + + $this->assertSame(100, $decodedJson['height']); + $this->assertInternalType("int", $decodedJson['height']); + + $this->assertSame(200, $decodedJson['width']); + $this->assertInternalType("int", $decodedJson['width']); + + $this->assertSame(300, $decodedJson['thumbheight']); + $this->assertInternalType("int", $decodedJson['thumbheight']); + + $this->assertSame(400, $decodedJson['thumbwidth']); + $this->assertInternalType("int", $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->assertInternalType("string", $decodedJson['nav']); + + $this->assertSame(true, $decodedJson['loop']); + $this->assertInternalType("bool", $decodedJson['loop']); + + $this->assertSame(false, $decodedJson['arrows']); + $this->assertInternalType("bool", $decodedJson['arrows']); + + $this->assertSame(true, $decodedJson['keyboard']); + $this->assertInternalType("bool", $decodedJson['keyboard']); + + $this->assertSame(true, $decodedJson['showCaption']); + $this->assertInternalType("bool", $decodedJson['showCaption']); + + $this->assertSame('vertical', $decodedJson['navdir']); + $this->assertInternalType("string", $decodedJson['navdir']); + + $this->assertSame(false, $decodedJson['navarrows']); + $this->assertInternalType("bool", $decodedJson['navarrows']); + + $this->assertSame(10, $decodedJson['thumbmargin']); + $this->assertInternalType("int", $decodedJson['thumbmargin']); + + $this->assertSame('thumbs', $decodedJson['navtype']); + $this->assertInternalType("string", $decodedJson['navtype']); + + $this->assertSame('dissolve', $decodedJson['transition']); + $this->assertInternalType("string", $decodedJson['transition']); + + $this->assertSame(300, $decodedJson['transitionduration']); + $this->assertInternalType("int", $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); + } +} 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 3630fddb326a7..aa6ffa1bd33c4 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 @@ - + + + Magento\Catalog\Block\Product\View\GalleryOptions + + 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..a810dc2916152 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 @@ -45,44 +45,8 @@ "mixins":["magnifier/magnify"], "magnifierOpts": getMagnifier() ?>, "data": getGalleryImagesJson() ?>, - "options": { - "nav": "getVar("gallery/nav") ?>", - "loop": getVar("gallery/loop") ? 'true' : 'false' ?>, - "keyboard": getVar("gallery/keyboard") ? 'true' : 'false' ?>, - "arrows": getVar("gallery/arrows") ? 'true' : 'false' ?>, - "allowfullscreen": getVar("gallery/allowfullscreen") ? 'true' : 'false' ?>, - "showCaption": getVar("gallery/caption") ? 'true' : 'false' ?>, - "width": "getImageAttribute('product_page_image_medium', 'width') ?>", - "thumbwidth": "getImageAttribute('product_page_image_small', 'width') ?>", - getImageAttribute('product_page_image_small', 'height') || $block->getImageAttribute('product_page_image_small', 'width')): ?> - "thumbheight": getImageAttribute('product_page_image_small', 'height') - ?: $block->getImageAttribute('product_page_image_small', 'width'); ?>, - - getImageAttribute('product_page_image_medium', 'height') || $block->getImageAttribute('product_page_image_medium', 'width')): ?> - "height": getImageAttribute('product_page_image_medium', 'height') - ?: $block->getImageAttribute('product_page_image_medium', 'width'); ?>, - - getVar("gallery/transition/duration")): ?> - "transitionduration": getVar("gallery/transition/duration") ?>, - - "transition": "getVar("gallery/transition/effect") ?>", - "navarrows": getVar("gallery/navarrows") ? 'true' : 'false' ?>, - "navtype": "getVar("gallery/navtype") ?>", - "navdir": "getVar("gallery/navdir") ?>" - }, - "fullscreen": { - "nav": "getVar("gallery/fullscreen/nav") ?>", - "loop": getVar("gallery/fullscreen/loop") ? 'true' : 'false' ?>, - "navdir": "getVar("gallery/fullscreen/navdir") ?>", - "navarrows": getVar("gallery/fullscreen/navarrows") ? 'true' : 'false' ?>, - "navtype": "getVar("gallery/fullscreen/navtype") ?>", - "arrows": getVar("gallery/fullscreen/arrows") ? 'true' : 'false' ?>, - "showCaption": getVar("gallery/fullscreen/caption") ? 'true' : 'false' ?>, - getVar("gallery/fullscreen/transition/duration")): ?> - "transitionduration": getVar("gallery/fullscreen/transition/duration") ?>, - - "transition": "getVar("gallery/fullscreen/transition/effect") ?>" - }, + "options": getGalleryOptions()->getOptionsJson() ?>, + "fullscreen": getGalleryOptions()->getFSOptionsJson() ?>, "breakpoints": getBreakpoints() ?> } } From dcc71bfccccd814980064208acd552a4a758a808 Mon Sep 17 00:00:00 2001 From: Graham Wharton Date: Mon, 18 Mar 2019 12:24:18 +0000 Subject: [PATCH 055/142] Removed Unnecessary type checking on tests --- .../Block/Product/View/GalleryOptionsTest.php | 52 ------------------- 1 file changed, 52 deletions(-) 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 3a5b96ec53267..5ade6af9fac33 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 @@ -125,52 +125,21 @@ public function testGetOptionsJson() $decodedJson = $this->jsonSerializer->unserialize($json); $this->assertSame('thumbs', $decodedJson['nav']); - $this->assertInternalType("string", $decodedJson['nav']); - $this->assertSame(false, $decodedJson['loop']); - $this->assertInternalType("bool", $decodedJson['loop']); - $this->assertSame(true, $decodedJson['keyboard']); - $this->assertInternalType("bool", $decodedJson['keyboard']); - $this->assertSame(true, $decodedJson['arrows']); - $this->assertInternalType("bool", $decodedJson['arrows']); - $this->assertSame(false, $decodedJson['showCaption']); - $this->assertInternalType("bool", $decodedJson['showCaption']); - $this->assertSame(true, $decodedJson['allowfullscreen']); - $this->assertInternalType("bool", $decodedJson['allowfullscreen']); - $this->assertSame('horizontal', $decodedJson['navdir']); - $this->assertInternalType("string", $decodedJson['navdir']); - $this->assertSame(true, $decodedJson['navarrows']); - $this->assertInternalType("bool", $decodedJson['navarrows']); - $this->assertSame('slides', $decodedJson['navtype']); - $this->assertInternalType("string", $decodedJson['navtype']); - $this->assertSame(5, $decodedJson['thumbmargin']); - $this->assertInternalType("int", $decodedJson['thumbmargin']); - $this->assertSame('slide', $decodedJson['transition']); - $this->assertInternalType("string", $decodedJson['transition']); - $this->assertSame(500, $decodedJson['transitionduration']); - $this->assertInternalType("int", $decodedJson['transitionduration']); - $this->assertSame(100, $decodedJson['height']); - $this->assertInternalType("int", $decodedJson['height']); - $this->assertSame(200, $decodedJson['width']); - $this->assertInternalType("int", $decodedJson['width']); - $this->assertSame(300, $decodedJson['thumbheight']); - $this->assertInternalType("int", $decodedJson['thumbheight']); - $this->assertSame(400, $decodedJson['thumbwidth']); - $this->assertInternalType("int", $decodedJson['thumbwidth']); } public function testGetFSOptionsJson() @@ -200,37 +169,16 @@ public function testGetFSOptionsJson() //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->assertInternalType("string", $decodedJson['nav']); - $this->assertSame(true, $decodedJson['loop']); - $this->assertInternalType("bool", $decodedJson['loop']); - $this->assertSame(false, $decodedJson['arrows']); - $this->assertInternalType("bool", $decodedJson['arrows']); - $this->assertSame(true, $decodedJson['keyboard']); - $this->assertInternalType("bool", $decodedJson['keyboard']); - $this->assertSame(true, $decodedJson['showCaption']); - $this->assertInternalType("bool", $decodedJson['showCaption']); - $this->assertSame('vertical', $decodedJson['navdir']); - $this->assertInternalType("string", $decodedJson['navdir']); - $this->assertSame(false, $decodedJson['navarrows']); - $this->assertInternalType("bool", $decodedJson['navarrows']); - $this->assertSame(10, $decodedJson['thumbmargin']); - $this->assertInternalType("int", $decodedJson['thumbmargin']); - $this->assertSame('thumbs', $decodedJson['navtype']); - $this->assertInternalType("string", $decodedJson['navtype']); - $this->assertSame('dissolve', $decodedJson['transition']); - $this->assertInternalType("string", $decodedJson['transition']); - $this->assertSame(300, $decodedJson['transitionduration']); - $this->assertInternalType("int", $decodedJson['transitionduration']); } public function testGetOptionsJsonOptionals() From f2483b5b679c60d63bb02848e015e7379aeb7e78 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev Date: Mon, 18 Mar 2019 15:11:21 +0200 Subject: [PATCH 056/142] Remove all marketing get params on Varnish to minimize the cache objects --- app/code/Magento/PageCache/etc/varnish4.vcl | 9 +++++---- app/code/Magento/PageCache/etc/varnish5.vcl | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/PageCache/etc/varnish4.vcl b/app/code/Magento/PageCache/etc/varnish4.vcl index 8068447e5ca99..c73c4e39170e6 100644 --- a/app/code/Magento/PageCache/etc/varnish4.vcl +++ b/app/code/Magento/PageCache/etc/varnish4.vcl @@ -91,10 +91,11 @@ sub vcl_recv { } } - # Remove Google gclid parameters to minimize the cache objects - set req.url = regsuball(req.url,"\?gclid=[^&]+$",""); # strips when QS = "?gclid=AAA" - set req.url = regsuball(req.url,"\?gclid=[^&]+&","?"); # strips when QS = "?gclid=AAA&foo=bar" - set req.url = regsuball(req.url,"&gclid=[^&]+",""); # strips when QS = "?foo=bar&gclid=AAA" or QS = "?foo=bar&gclid=AAA&bar=baz" + # 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+()%.]+&?", ""); + set req.url = regsub(req.url, "[?|&]+$", ""); + } # Static files caching if (req.url ~ "^/(pub/)?(media|static)/") { diff --git a/app/code/Magento/PageCache/etc/varnish5.vcl b/app/code/Magento/PageCache/etc/varnish5.vcl index 6c8414a5cb641..ea586858eff75 100644 --- a/app/code/Magento/PageCache/etc/varnish5.vcl +++ b/app/code/Magento/PageCache/etc/varnish5.vcl @@ -92,10 +92,11 @@ sub vcl_recv { } } - # Remove Google gclid parameters to minimize the cache objects - set req.url = regsuball(req.url,"\?gclid=[^&]+$",""); # strips when QS = "?gclid=AAA" - set req.url = regsuball(req.url,"\?gclid=[^&]+&","?"); # strips when QS = "?gclid=AAA&foo=bar" - set req.url = regsuball(req.url,"&gclid=[^&]+",""); # strips when QS = "?foo=bar&gclid=AAA" or QS = "?foo=bar&gclid=AAA&bar=baz" + # 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+()%.]+&?", ""); + set req.url = regsub(req.url, "[?|&]+$", ""); + } # Static files caching if (req.url ~ "^/(pub/)?(media|static)/") { From 6c0c2fa0b41fce525cec017645454df64b52ac52 Mon Sep 17 00:00:00 2001 From: Graham Wharton Date: Tue, 19 Mar 2019 09:51:28 +0000 Subject: [PATCH 057/142] Ignore PHPMD Else Expression warnings --- app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php b/app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php index 084da345a12d4..dd2c62174a734 100644 --- a/app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php +++ b/app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php @@ -48,6 +48,7 @@ public function __construct( * @return string * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ElseExpression) */ public function getOptionsJson() { @@ -111,6 +112,7 @@ public function getOptionsJson() * @return string * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ElseExpression) */ public function getFSOptionsJson() { From 799f37e98cae41b394a8983b5cf96b7b98cde2d2 Mon Sep 17 00:00:00 2001 From: Vasilii Date: Thu, 21 Mar 2019 09:44:31 +0200 Subject: [PATCH 058/142] magento/graphql-ce:#468 - Fix codestyle issue # Fixed issue "@throws annotation tags are added only when exception is thrown explicitly in the function" --- .../Cart/CreateQuoteAddressByCustomerAddress.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateQuoteAddressByCustomerAddress.php b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateQuoteAddressByCustomerAddress.php index 2e2588ea81068..ba46f5621ee82 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/CreateQuoteAddressByCustomerAddress.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/CreateQuoteAddressByCustomerAddress.php @@ -9,12 +9,8 @@ use Magento\CustomerGraphQl\Model\Customer\Address\GetCustomerAddress; use Magento\CustomerGraphQl\Model\Customer\GetCustomer; -use Magento\Framework\GraphQl\Exception\GraphQlAuthenticationException; -use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; -use Magento\Framework\GraphQl\Exception\GraphQlInputException; -use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; -use Magento\Quote\Model\Quote\Address; 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 @@ -55,11 +51,8 @@ public function __construct( * @param ContextInterface $context * @param int|string|null $customerAddressId * @param array|null $customerAddress + * * @return Address - * @throws GraphQlAuthenticationException - * @throws GraphQlAuthorizationException - * @throws GraphQlInputException - * @throws GraphQlNoSuchEntityException */ public function execute( ContextInterface $context, From 8ff613ebef8d20bed5a0abab8047e9afb26ff92e Mon Sep 17 00:00:00 2001 From: Yurii Sapiha Date: Thu, 21 Mar 2019 19:17:03 +0200 Subject: [PATCH 059/142] MAGETWO-98335: Unable to find product on product grid page using store view level attribute --- ...lterByNameByStoreViewOnProductGridTest.xml | 45 +++++++++++++ .../Product/ProductCollection.php | 63 +++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/Test/AdminFilterByNameByStoreViewOnProductGridTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilterByNameByStoreViewOnProductGridTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilterByNameByStoreViewOnProductGridTest.xml new file mode 100644 index 0000000000000..f3ec225540c75 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilterByNameByStoreViewOnProductGridTest.xml @@ -0,0 +1,45 @@ + + + + + + + + + + <description value="Verify that products grid can be filtered on all store view level by attribute"/> + <severity value="MAJOR"/> + <testCaseId value="MAGETWO-98755"/> + <useCaseId value="MAGETWO-98335"/> + <group value="catalog"/> + </annotations> + <before> + <createData entity="SimpleProduct2" stepKey="createSimpleProduct"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <actionGroup ref="ClearProductsFilterActionGroup" stepKey="clearProductsFilter"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <amOnPage url="{{AdminProductEditPage.url($$createSimpleProduct.id$$)}}" stepKey="goToEditPage"/> + <actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="switchToDefaultStoreView"> + <argument name="storeView" value="_defaultStore.name"/> + </actionGroup> + <scrollToTopOfPage stepKey="scrollToTopOfAdminProductFormSection"/> + <click selector="{{AdminProductFormSection.productNameUseDefault}}" stepKey="uncheckUseDefault"/> + <fillField selector="{{AdminProductFormSection.productName}}" userInput="{{SimpleProduct.name}}" stepKey="fillNewName"/> + <actionGroup ref="saveProductForm" stepKey="saveSimpleProduct"/> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> + <actionGroup ref="filterProductGridByName" stepKey="filterGridByName"> + <argument name="product" value="SimpleProduct"/> + </actionGroup> + <see selector="{{AdminProductGridSection.firstProductRow}}" userInput="{{SimpleProduct2.name}}" stepKey="seeProductNameInGrid"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductCollection.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductCollection.php index f4334bc25efd8..37ac5c85c6f67 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductCollection.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductCollection.php @@ -5,6 +5,10 @@ */ namespace Magento\Catalog\Ui\DataProvider\Product; +use Magento\Catalog\Model\ResourceModel\Eav\Attribute; +use Magento\Framework\Exception\LocalizedException; +use Magento\Eav\Model\Entity\Attribute\AttributeInterface; + /** * Collection which is used for rendering product list in the backend. * @@ -25,4 +29,63 @@ protected function _productLimitationJoinPrice() $this->_productLimitationFilters->setUsePriceIndex(false); return $this->_productLimitationPrice(true); } + + /** + * Add attribute filter to collection + * + * @param AttributeInterface|integer|string|array $attribute + * @param null|string|array $condition + * @param string $joinType + * @return $this + * @throws LocalizedException + */ + public function addAttributeToFilter($attribute, $condition = null, $joinType = 'inner') + { + $storeId = (int)$this->getStoreId(); + if ($attribute === 'is_saleable' + || is_array($attribute) + || $storeId !== $this->getDefaultStoreId() + ) { + return parent::addAttributeToFilter($attribute, $condition, $joinType); + } + + if ($attribute instanceof AttributeInterface) { + $attributeModel = $attribute; + } else { + $attributeModel = $this->getEntity()->getAttribute($attribute); + if ($attributeModel === false) { + throw new LocalizedException( + __('Invalid attribute identifier for filter (%1)', get_class($attribute)) + ); + } + } + + if ($attributeModel->isScopeGlobal() || $attributeModel->getBackend()->isStatic()) { + return parent::addAttributeToFilter($attribute, $condition, $joinType); + } + + $this->addAttributeToFilterAllStores($attributeModel, $condition); + + return $this; + } + + /** + * Add attribute to filter by all stores + * + * @param Attribute $attributeModel + * @param array $condition + * @return void + */ + private function addAttributeToFilterAllStores(Attribute $attributeModel, array $condition): void + { + $tableName = $this->getTable($attributeModel->getBackendTable()); + $entity = $this->getEntity(); + $fKey = 'e.' . $this->getEntityPkName($entity); + $pKey = $tableName . '.' . $this->getEntityPkName($entity); + $condition = "({$pKey} = {$fKey}) AND (" + . $this->_getConditionSql("{$tableName}.value", $condition) + . ')'; + $selectExistsInAllStores = $this->getConnection()->select()->from($tableName); + $this->getSelect()->exists($selectExistsInAllStores, $condition); + } } From 875313e745a9c06cb777308fa53eb7952e6ce0eb Mon Sep 17 00:00:00 2001 From: Davit_Zakharyan <davit_zakharyan@epam.com> Date: Fri, 22 Mar 2019 16:32:36 +0400 Subject: [PATCH 060/142] MAGETWO-65232: Product name does not display special characters properly - Updated automated test script. --- .../Test/Mftf/Section/StorefrontNavigationSection.xml | 2 +- .../Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontNavigationSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontNavigationSection.xml index 0263e218c2417..292b2d7008bc1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontNavigationSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontNavigationSection.xml @@ -12,6 +12,6 @@ <element name="subCategory" type="button" selector="//ul[contains(@class,'submenu')]//span[contains(text(),'{{var1}}')]" parameterized="true"/> <element name="breadcrumbs" type="textarea" selector=".items"/> <element name="categoryBreadcrumbs" type="textarea" selector=".breadcrumbs li"/> - <element name="categoryBreadcrumbsByNumber" type="textarea" selector=".breadcrumbs li:nth-of-type({{var1}})" parameterized="true"/> + <element name="categoryBreadcrumbsByNumber" type="textarea" selector=".breadcrumbs li:nth-of-type({{number}})" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml index 990e488e9c662..47fad10977b7c 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml @@ -52,6 +52,13 @@ <waitForPageLoad stepKey="waitForInvoicePageLoad"/> </actionGroup> + <actionGroup name="clearInvoicesGridFilers"> + <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"/> From dfd8b12280e255da6d97dbfc7272194b258e3b41 Mon Sep 17 00:00:00 2001 From: amol2jcommerce <amol@twojay.in> Date: Fri, 22 Mar 2019 18:32:08 +0530 Subject: [PATCH 061/142] changes for contact us layout in I-pad --- .../Magento/Contact/view/frontend/web/css/source/_module.less | 1 + 1 file changed, 1 insertion(+) 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 0aaec05aa2afe..b31c0731c7924 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 @@ -16,6 +16,7 @@ .form.contact { float: none; width: 50%; + min-width: 600px; } } } From 4fd4281c3756748a67b82d4203ad650b89bc0c83 Mon Sep 17 00:00:00 2001 From: amol2jcommerce <amol@twojay.in> Date: Fri, 22 Mar 2019 19:31:40 +0530 Subject: [PATCH 062/142] changes for contact us layout in I-pad --- .../Magento/Contact/view/frontend/web/css/source/_module.less | 1 + 1 file changed, 1 insertion(+) 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 b31c0731c7924..cb41e025d665c 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 @@ -36,6 +36,7 @@ .form.contact { float: none; width: 100%; + min-width: auto; } } } From 34a7ec56dcc220a1983d48bc714aa3ed14daac8b Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Sat, 23 Mar 2019 03:12:09 +0200 Subject: [PATCH 063/142] Convert CaptchaEditCustomerTest to MFTF --- .../Mftf/Test/CaptchaEditCustomerTest.xml | 74 +++++++++++++++++++ ...frontCustomerAccountInformationSection.xml | 7 +- 2 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml new file mode 100644 index 0000000000000..dbead37c55500 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml @@ -0,0 +1,74 @@ +<?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="CaptchaEditCustomerEmailTest"> + <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."/> + <description value="Test for checking captcha on the customer account edit page and customer is locked."/> + <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"/> + <createData entity="Simple_US_Customer" stepKey="customer"/> + <!-- Sign in as customer --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> + <argument name="Customer" value="$$customer$$"/> + </actionGroup> + </before> + <after> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + <!-- Revert Captcha forms configurations --> + <magentoCLI command="config:set customer/captcha/forms user_login,user_forgotpassword" stepKey="enableUserEditCaptcha"/> + <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches1"/> + </after> + + <!-- Open Customer edit page --> + <amOnPage url="/customer/account/edit/" stepKey="goToEditPage"/> + <waitForPageLoad stepKey="waitForEditPage"/> + + <!-- Update email with incorrect password 3 times. --> + <click selector="{{StorefrontCustomerAccountInformationSection.changeEmail}}" stepKey="clickChangeEmailCheckbox1"/> + <fillField selector="{{StorefrontCustomerAccountInformationSection.currentPassword}}" userInput="incorrectPassword" stepKey="enterWrongPassword1"/> + <click selector="{{StorefrontCustomerAccountInformationSection.saveButton}}" stepKey="saveChange1"/> + <see userInput="The password doesn't match this account. Verify the password and try again." selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="verifyMessage1"/> + + <click selector="{{StorefrontCustomerAccountInformationSection.changeEmail}}" stepKey="clickChangeEmailCheckbox2"/> + <fillField selector="{{StorefrontCustomerAccountInformationSection.currentPassword}}" userInput="incorrectPassword" stepKey="enterWrongPassword2"/> + <click selector="{{StorefrontCustomerAccountInformationSection.saveButton}}" stepKey="saveChange2"/> + <see userInput="The password doesn't match this account. Verify the password and try again." selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="verifyMessage2"/> + + <click selector="{{StorefrontCustomerAccountInformationSection.changeEmail}}" stepKey="clickChangeEmailCheckbox3"/> + <fillField selector="{{StorefrontCustomerAccountInformationSection.currentPassword}}" userInput="incorrectPassword" stepKey="enterWrongPassword3"/> + <click selector="{{StorefrontCustomerAccountInformationSection.saveButton}}" stepKey="saveChange3"/> + <see userInput="The password doesn't match this account. Verify the password and try again." selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="verifyMessage3"/> + + <!-- Check captcha visibility after incorrect password submit form --> + <waitForElementVisible selector="{{StorefrontCustomerEditFormSection.captchaField}}" stepKey="seeCaptchaField"/> + <waitForElementVisible selector="{{StorefrontCustomerEditFormSection.captchaImg}}" stepKey="seeCaptchaImage"/> + <waitForElementVisible selector="{{StorefrontCustomerEditFormSection.captchaReload}}" stepKey="seeCaptchaReloadButton"/> + <reloadPage stepKey="refreshPage"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + <waitForElementVisible selector="{{StorefrontCustomerEditFormSection.captchaField}}" stepKey="seeCaptchaField2"/> + <waitForElementVisible selector="{{StorefrontCustomerEditFormSection.captchaImg}}" stepKey="seeCaptchaImage2"/> + <waitForElementVisible selector="{{StorefrontCustomerEditFormSection.captchaReload}}" stepKey="seeCaptchaReloadButton2"/> + + <!-- Try to submit for with incorrect captcha --> + <click selector="{{StorefrontCustomerAccountInformationSection.changeEmail}}" stepKey="clickChangeEmailCheckbox4"/> + <fillField selector="{{StorefrontCustomerAccountInformationSection.currentPassword}}" userInput="incorrectPassword" stepKey="enterWrongPassword4"/> + <fillField selector="{{StorefrontCustomerEditFormSection.captchaField}}" userInput="wrongCaptcha" stepKey="enterWrongCaptcha"/> + <click selector="{{StorefrontCustomerAccountInformationSection.saveButton}}" stepKey="saveChange4"/> + <see userInput="Incorrect CAPTCHA" selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="verifyMessage4"/> + </test> +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml index b819a78002c62..e93985b4f469b 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml @@ -11,13 +11,16 @@ <section name="StorefrontCustomerAccountInformationSection"> <element name="firstName" type="input" selector="#firstname"/> <element name="lastName" type="input" selector="#lastname"/> - <element name="changeEmail" type="checkbox" selector="#change_email"/> - <element name="changePassword" type="checkbox" selector="#change_password"/> + <element name="changeEmail" type="checkbox" selector="#change-email"/> + <element name="changePassword" type="checkbox" selector="#change-password"/> <element name="testAddedAttributeFiled" type="input" selector="//input[contains(@id,'{{var}}')]" parameterized="true"/> <element name="saveButton" type="button" selector="#form-validate .action.save.primary" timeout="30"/> <element name="currentPassword" type="input" selector="#current-password"/> <element name="newPassword" type="input" selector="#password"/> <element name="confirmNewPassword" type="input" selector="#password-confirmation"/> <element name="confirmNewPasswordError" type="text" selector="#password-confirmation-error"/> + <element name="captchaField" type="input" selector="#captcha_user_edit"/> + <element name="captchaImg" type="block" selector=".captcha-img"/> + <element name="captchaReload" type="block" selector=".captcha-reload"/> </section> </sections> From d3970362db0455451f014a133d8ca297f96c0c87 Mon Sep 17 00:00:00 2001 From: Systaliuk Kostiantyn <leandry@atwix.com> Date: Sat, 23 Mar 2019 13:05:29 +0200 Subject: [PATCH 064/142] Fix stepKey and comment typos --- .../Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml index dbead37c55500..646c9af3ba55f 100644 --- a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml +++ b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaEditCustomerTest.xml @@ -30,8 +30,8 @@ <after> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> <!-- Revert Captcha forms configurations --> - <magentoCLI command="config:set customer/captcha/forms user_login,user_forgotpassword" stepKey="enableUserEditCaptcha"/> - <magentoCLI command="cache:clean config full_page" stepKey="cleanInvalidatedCaches1"/> + <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 edit page --> @@ -64,7 +64,7 @@ <waitForElementVisible selector="{{StorefrontCustomerEditFormSection.captchaImg}}" stepKey="seeCaptchaImage2"/> <waitForElementVisible selector="{{StorefrontCustomerEditFormSection.captchaReload}}" stepKey="seeCaptchaReloadButton2"/> - <!-- Try to submit for with incorrect captcha --> + <!-- Try to submit form with incorrect captcha --> <click selector="{{StorefrontCustomerAccountInformationSection.changeEmail}}" stepKey="clickChangeEmailCheckbox4"/> <fillField selector="{{StorefrontCustomerAccountInformationSection.currentPassword}}" userInput="incorrectPassword" stepKey="enterWrongPassword4"/> <fillField selector="{{StorefrontCustomerEditFormSection.captchaField}}" userInput="wrongCaptcha" stepKey="enterWrongCaptcha"/> From b2268d07c0451cde97d71b41cd9099884ac93f04 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Sat, 23 Mar 2019 16:09:12 +0200 Subject: [PATCH 065/142] Convert CaptchaOnStoreFrontRegisterTest to MFTF --- .../Test/CaptchaOnStoreFrontRegisterTest.xml | 51 +++++++++++++++++++ .../StorefrontCustomerCreateFormSection.xml | 3 ++ 2 files changed, 54 insertions(+) create mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontRegisterTest.xml diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontRegisterTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontRegisterTest.xml new file mode 100644 index 0000000000000..86a660563086e --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontRegisterTest.xml @@ -0,0 +1,51 @@ +<?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/Customer/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml index 8881a2a012ce8..68851e88ec4b2 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml @@ -17,6 +17,9 @@ <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" /> From 2302d11380584bc8c2787df55b064b7fb62b7e8c Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sat, 23 Mar 2019 15:59:08 +0100 Subject: [PATCH 066/142] Convert ResetCustomerPasswordFailedTest to MFTF --- ...refrontResetCustomerPasswordFailedTest.xml | 47 +++++++++++++++++++ .../ResetCustomerPasswordFailedTest.xml | 1 + 2 files changed, 48 insertions(+) create mode 100644 app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml new file mode 100644 index 0000000000000..7050050097874 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontResetCustomerPasswordFailedTest.xml @@ -0,0 +1,47 @@ +<?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"> + <annotations> + <features value="Customer"/> + <title value="Customer tries to reset password several times"/> + <description value="Customer tries to reset password several times"/> + <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> + <deleteData stepKey="deleteCustomer" createDataKey="customer" /> + </after> + <!-- Go to login page, and click on the forgot password link --> + <amOnPage stepKey="amOnSignInPage1" url="{{StorefrontCustomerSignInPage.url}}"/> + <click stepKey="clickForgotPasswordLink1" selector="{{StorefrontCustomerSignInFormSection.forgotPasswordLink}}"/> + <see stepKey="seePageTitle1" userInput="Forgot Your Password" selector="{{StorefrontForgotPasswordSection.pageTitle}}"/> + <!-- Enter email and submit the forgot password form --> + <fillField stepKey="enterEmail1" userInput="$$customer.email$$" selector="{{StorefrontForgotPasswordSection.email}}"/> + <click stepKey="clickResetPassword1" selector="{{StorefrontForgotPasswordSection.resetMyPasswordButton}}"/> + <seeInCurrentUrl stepKey="seeInSignInPage" url="account/login"/> + <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.successMessage}}" stepKey="waitForSuccessMessage" /> + <see stepKey="seeSuccessMessage" userInput="If there is an account associated with $$customer.email$$ you will receive an email with a link to reset your password." selector="{{StorefrontCustomerLoginMessagesSection.successMessage}}"/> + <!-- Repeat the procedure once again and ensure that on a second attempt customer sees an error --> + <amOnPage stepKey="amOnSignInPage2" url="{{StorefrontCustomerSignInPage.url}}"/> + <click stepKey="clickForgotPasswordLink2" selector="{{StorefrontCustomerSignInFormSection.forgotPasswordLink}}"/> + <see stepKey="seePageTitle2" userInput="Forgot Your Password" selector="{{StorefrontForgotPasswordSection.pageTitle}}"/> + <fillField stepKey="enterEmail2" userInput="$$customer.email$$" selector="{{StorefrontForgotPasswordSection.email}}"/> + <click stepKey="clickResetPassword2" selector="{{StorefrontForgotPasswordSection.resetMyPasswordButton}}"/> + <seeInCurrentUrl stepKey="seeInForgotPasswordPage" url="account/forgotpassword"/> + <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" stepKey="waitForFailMessage" /> + <see stepKey="seeFailMessage" userInput="We received too many requests for password resets. Please wait and try again later or contact hello@example.com." selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}"/> + </test> +</tests> 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 0b5b8a059cbbd..524f57c78b4ba 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,6 +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="customer/dataset" xsi:type="string">customer_US</data> <data name="attempts" xsi:type="string">2</data> From ae4f83491abafc882ab4f29be0eebbe5994f642e Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Sat, 23 Mar 2019 23:22:24 +0200 Subject: [PATCH 067/142] Convert CaptchaOnStoreFrontLoginTest to MFTF --- .../Test/CaptchaOnStoreFrontLoginTest.xml | 62 +++++++++++++++++++ .../StorefrontCustomerSignInFormSection.xml | 3 + 2 files changed, 65 insertions(+) create mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontLoginTest.xml diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontLoginTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontLoginTest.xml new file mode 100644 index 0000000000000..59de69b1d2b0d --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnStoreFrontLoginTest.xml @@ -0,0 +1,62 @@ +<?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/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml index f52b379379ad1..a6f41fb63415c 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml @@ -13,6 +13,9 @@ <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"/> </section> <section name="StorefrontCustomerSignInPopupFormSection"> <element name="errorMessage" type="input" selector="[data-ui-id='checkout-cart-validationmessages-message-error']"/> From dd3eb459660b79acd6a8b34afaea1a3e7d83e3fb Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Sun, 24 Mar 2019 00:30:15 +0200 Subject: [PATCH 068/142] Convert CaptchaOnContactUsTest to MFTF --- .../StorefrontContactUsFormSection.xml | 20 +++++++ .../Test/Mftf/Test/CaptchaOnContactUsTest.xml | 54 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsFormSection.xml create mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnContactUsTest.xml 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..235712b0b5b57 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Section/StorefrontContactUsFormSection.xml @@ -0,0 +1,20 @@ +<?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="#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> diff --git a/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnContactUsTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnContactUsTest.xml new file mode 100644 index 0000000000000..64978f32aa61a --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnContactUsTest.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="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="cleanInvalidatedCaches1"/> + <createData entity="Simple_US_Customer" stepKey="customer"/> + </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"/> + </after> + + <!-- Open storefront contact us form --> + <amOnPage url="/contact/" stepKey="amOnContactUpPage"/> + <waitForPageLoad stepKey="waitForContactUpPage"/> + + <!-- Check Captcha items --> + <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaField}}" stepKey="seeCaptchaField1"/> + <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaImg}}" stepKey="seeCaptchaImage1"/> + <waitForElementVisible selector="{{StorefrontContactUsFormSection.captchaReload}}" stepKey="seeCaptchaReloadButton1"/> + + <!-- 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" /> + <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"/> + </test> +</tests> From c3e4f07b3d377dce75c3968d2d9ced1c3d31538f Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Fri, 15 Mar 2019 12:14:43 +0200 Subject: [PATCH 069/142] fix-issue-21755 --- .../Event/Invoker/InvokerDefault.php | 30 ++++++++++++++++--- .../Test/Unit/Invoker/InvokerDefaultTest.php | 13 ++++++-- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/lib/internal/Magento/Framework/Event/Invoker/InvokerDefault.php b/lib/internal/Magento/Framework/Event/Invoker/InvokerDefault.php index a7a387b5def81..acd0a61633557 100644 --- a/lib/internal/Magento/Framework/Event/Invoker/InvokerDefault.php +++ b/lib/internal/Magento/Framework/Event/Invoker/InvokerDefault.php @@ -9,7 +9,12 @@ namespace Magento\Framework\Event\Invoker; use Magento\Framework\Event\Observer; +use Psr\Log\LoggerInterface; +use Magento\Framework\App\State; +/** + * Default Invoker. + */ class InvokerDefault implements \Magento\Framework\Event\InvokerInterface { /** @@ -22,20 +27,29 @@ class InvokerDefault implements \Magento\Framework\Event\InvokerInterface /** * Application state * - * @var \Magento\Framework\App\State + * @var State */ protected $_appState; + /** + * @var LoggerInterface + */ + private $logger; + /** * @param \Magento\Framework\Event\ObserverFactory $observerFactory - * @param \Magento\Framework\App\State $appState + * @param State $appState + * @param LoggerInterface $logger */ public function __construct( \Magento\Framework\Event\ObserverFactory $observerFactory, - \Magento\Framework\App\State $appState + State $appState, + LoggerInterface $logger = null ) { $this->_observerFactory = $observerFactory; $this->_appState = $appState; + $this->logger = $logger ?: \Magento\Framework\App\ObjectManager::getInstance() + ->get(LoggerInterface::class); } /** @@ -61,6 +75,8 @@ public function dispatch(array $configuration, Observer $observer) } /** + * Execute Observer. + * * @param \Magento\Framework\Event\ObserverInterface $object * @param Observer $observer * @return $this @@ -70,7 +86,7 @@ protected function _callObserverMethod($object, $observer) { if ($object instanceof \Magento\Framework\Event\ObserverInterface) { $object->execute($observer); - } elseif ($this->_appState->getMode() == \Magento\Framework\App\State::MODE_DEVELOPER) { + } elseif ($this->_appState->getMode() == State::MODE_DEVELOPER) { throw new \LogicException( sprintf( 'Observer "%s" must implement interface "%s"', @@ -78,6 +94,12 @@ protected function _callObserverMethod($object, $observer) \Magento\Framework\Event\ObserverInterface::class ) ); + } else { + $this->logger->warning(sprintf( + 'Observer "%s" must implement interface "%s"', + get_class($object), + \Magento\Framework\Event\ObserverInterface::class + )); } return $this; } 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 37f650dbef6a0..82e660913ddc1 100644 --- a/lib/internal/Magento/Framework/Event/Test/Unit/Invoker/InvokerDefaultTest.php +++ b/lib/internal/Magento/Framework/Event/Test/Unit/Invoker/InvokerDefaultTest.php @@ -32,6 +32,11 @@ class InvokerDefaultTest extends \PHPUnit\Framework\TestCase */ protected $_invokerDefault; + /** + * @var |Psr\Log|LoggerInterface + */ + private $loggerMock; + protected function setUp() { $this->_observerFactoryMock = $this->createMock(\Magento\Framework\Event\ObserverFactory::class); @@ -41,10 +46,12 @@ protected function setUp() ['execute'] ); $this->_appStateMock = $this->createMock(\Magento\Framework\App\State::class); + $this->loggerMock = $this->createMock(\Psr\Log\LoggerInterface::class); $this->_invokerDefault = new \Magento\Framework\Event\Invoker\InvokerDefault( $this->_observerFactoryMock, - $this->_appStateMock + $this->_appStateMock, + $this->loggerMock ); } @@ -166,13 +173,15 @@ public function testWrongInterfaceCallWithDisabledDeveloperMode($shared) $this->returnValue($notObserver) ); $this->_appStateMock->expects( - $this->once() + $this->exactly(2) )->method( 'getMode' )->will( $this->returnValue(\Magento\Framework\App\State::MODE_PRODUCTION) ); + $this->loggerMock->expects($this->once())->method('warning'); + $this->_invokerDefault->dispatch( [ 'shared' => $shared, From 9c1dc7ec97d7e9a942f809da5095073261e5c8ed Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Sun, 24 Mar 2019 19:40:46 +0200 Subject: [PATCH 070/142] Convert CaptchaOnAdminLoginTest to MFTF --- .../Mftf/Section/AdminLoginFormSection.xml | 4 ++ .../Mftf/Test/CaptchaOnAdminLoginTest.xml | 62 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnAdminLoginTest.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml index 3b10fac7bb9dc..8b28e923cc017 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml @@ -12,5 +12,9 @@ <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/Captcha/Test/Mftf/Test/CaptchaOnAdminLoginTest.xml b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnAdminLoginTest.xml new file mode 100644 index 0000000000000..80f1832200fc1 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Mftf/Test/CaptchaOnAdminLoginTest.xml @@ -0,0 +1,62 @@ +<?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 --> + <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"/> + + <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"/> + + <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"/> + + <!-- 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"/> + + <!-- 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"/> + <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"/> + </test> +</tests> From a71f53ac7a42648499e6faf425e018990c6d6d87 Mon Sep 17 00:00:00 2001 From: amol2jcommerce <amol@twojay.in> Date: Mon, 25 Mar 2019 10:57:16 +0530 Subject: [PATCH 071/142] changes for contact-us-layout-ipad-not-proper-2.3 --- .../view/frontend/web/css/source/_module.less | 12 ++++++++++-- 1 file changed, 10 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 cb41e025d665c..a9454bb6be253 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 @@ -16,12 +16,21 @@ .form.contact { float: none; width: 50%; - min-width: 600px; } } } } +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .contact-index-index .column:not(.sidebar-additional) .form.contact { + min-width: 600px; + } +} + // Mobile .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { .contact-index-index { @@ -36,7 +45,6 @@ .form.contact { float: none; width: 100%; - min-width: auto; } } } From 42ed84a97209f120655261fdb290bef9b456c6d3 Mon Sep 17 00:00:00 2001 From: Veronika Kurochkina <veronika_kurochkina@epam.com> Date: Mon, 25 Mar 2019 14:27:39 +0300 Subject: [PATCH 072/142] MAGETWO-65232: Product name does not display special characters properly - Add strict type declaration --- .../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 882fec2ab7c46..64e569977429c 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 @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Sales\Model\Order\Pdf\Items\Creditmemo; /** 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 9c183ed44c72a..4a77053521e4a 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 @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Sales\Model\Order\Pdf\Items\Invoice; /** 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 c175b9866fb8e..fd18830e45b6e 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 @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Sales\Model\Order\Pdf\Items\Shipment; /** From c289f5dd45e879c48b2dda152985de7611174e15 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Mon, 25 Mar 2019 14:42:53 +0300 Subject: [PATCH 073/142] MAGETWO-70232: [GITHUB] Import customizable options adds it to another product if same SKU is filled#9457 - code refactoring; --- app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php index 4d5dd57b76f61..6b2f3aba12e7a 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Catalog\Model\Product\Option; use Magento\Catalog\Api\ProductCustomOptionRepositoryInterface as OptionRepository; @@ -71,7 +73,7 @@ public function execute($entity, $arguments = []) * @param bool $hasChangedSku * @param string $newSku */ - private function processOptionsSaving($options, $hasChangedSku, $newSku) + private function processOptionsSaving(array $options, bool $hasChangedSku, string $newSku) { foreach ($options as $option) { if ($hasChangedSku && $option->hasData('product_sku')) { From 222fd6570e88050185cebe08e58842862bca6615 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Mon, 25 Mar 2019 15:06:12 +0300 Subject: [PATCH 074/142] MAGETWO-64838: Unable to create order from store front if customer address custom attribute is required - code refactoring; --- app/code/Magento/Customer/Model/FileProcessor.php | 2 ++ .../Magento/Framework/Webapi/ServiceInputProcessor.php | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Model/FileProcessor.php b/app/code/Magento/Customer/Model/FileProcessor.php index e7e235b31fe49..c16faea284296 100644 --- a/app/code/Magento/Customer/Model/FileProcessor.php +++ b/app/code/Magento/Customer/Model/FileProcessor.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Customer\Model; /** diff --git a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php index 96f06e93a0411..f8fe514903ea8 100644 --- a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php +++ b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php @@ -349,7 +349,7 @@ protected function convertCustomAttributeValue($customAttributesValueArray, $dat * * @return array */ - private function getAttributesPreprocessorsMap() + private function getAttributesPreprocessorsMap(): array { if (!$this->attributesPreprocessorsMap) { foreach ($this->customAttributePreprocessors as $attributePreprocessor) { @@ -368,7 +368,7 @@ private function getAttributesPreprocessorsMap() * @param string $key * @param mixed $customAttribute */ - private function runCustomAttributePreprocessors($key, &$customAttribute) + private function runCustomAttributePreprocessors(string $key, &$customAttribute) { $preprocessorsMap = $this->getAttributesPreprocessorsMap(); if ($key && is_array($customAttribute) && array_key_exists($key, $preprocessorsMap)) { From ae14c96dc6e68f8a8814b728d6fd536577bbd6e5 Mon Sep 17 00:00:00 2001 From: Pieter Hoste <hoste.pieter@gmail.com> Date: Mon, 25 Mar 2019 20:42:00 +0100 Subject: [PATCH 075/142] Removing obsolete non-English translation files, these aren't translated and serve no purpose. --- app/code/Magento/Developer/i18n/de_DE.csv | 5 ----- app/code/Magento/Developer/i18n/es_ES.csv | 5 ----- app/code/Magento/Developer/i18n/fr_FR.csv | 5 ----- app/code/Magento/Developer/i18n/nl_NL.csv | 5 ----- app/code/Magento/Developer/i18n/pt_BR.csv | 5 ----- app/code/Magento/Developer/i18n/zh_Hans_CN.csv | 5 ----- app/code/Magento/Msrp/i18n/de_DE.csv | 2 -- app/code/Magento/Msrp/i18n/es_ES.csv | 2 -- app/code/Magento/Msrp/i18n/fr_FR.csv | 2 -- app/code/Magento/Msrp/i18n/nl_NL.csv | 2 -- app/code/Magento/Msrp/i18n/pt_BR.csv | 2 -- app/code/Magento/Msrp/i18n/zh_Hans_CN.csv | 2 -- app/code/Magento/ProductVideo/i18n/de_DE.csv | 10 ---------- app/code/Magento/ProductVideo/i18n/es_ES.csv | 10 ---------- app/code/Magento/ProductVideo/i18n/fr_FR.csv | 10 ---------- app/code/Magento/ProductVideo/i18n/nl_NL.csv | 10 ---------- app/code/Magento/ProductVideo/i18n/pt_BR.csv | 10 ---------- app/code/Magento/ProductVideo/i18n/zh_Hans_CN.csv | 10 ---------- app/code/Magento/Search/i18n/de_DE.csv | 1 - app/code/Magento/Search/i18n/es_ES.csv | 1 - app/code/Magento/Search/i18n/fr_FR.csv | 1 - app/code/Magento/Search/i18n/nl_NL.csv | 1 - app/code/Magento/Search/i18n/pt_BR.csv | 1 - app/code/Magento/Search/i18n/zh_Hans_CN.csv | 1 - app/code/Magento/Swatches/i18n/de_DE.csv | 2 -- app/code/Magento/Swatches/i18n/es_ES.csv | 2 -- app/code/Magento/Swatches/i18n/fr_FR.csv | 2 -- app/code/Magento/Swatches/i18n/nl_NL.csv | 2 -- app/code/Magento/Swatches/i18n/pt_BR.csv | 2 -- app/code/Magento/Swatches/i18n/zh_Hans_CN.csv | 2 -- app/code/Magento/Ui/i18n/de_DE.csv | 4 ---- app/code/Magento/Ui/i18n/es_ES.csv | 4 ---- app/code/Magento/Ui/i18n/fr_FR.csv | 4 ---- app/code/Magento/Ui/i18n/nl_NL.csv | 4 ---- app/code/Magento/Ui/i18n/pt_BR.csv | 4 ---- app/code/Magento/Ui/i18n/zh_Hans_CN.csv | 4 ---- 36 files changed, 144 deletions(-) delete mode 100644 app/code/Magento/Developer/i18n/de_DE.csv delete mode 100644 app/code/Magento/Developer/i18n/es_ES.csv delete mode 100644 app/code/Magento/Developer/i18n/fr_FR.csv delete mode 100644 app/code/Magento/Developer/i18n/nl_NL.csv delete mode 100644 app/code/Magento/Developer/i18n/pt_BR.csv delete mode 100644 app/code/Magento/Developer/i18n/zh_Hans_CN.csv delete mode 100644 app/code/Magento/Msrp/i18n/de_DE.csv delete mode 100644 app/code/Magento/Msrp/i18n/es_ES.csv delete mode 100644 app/code/Magento/Msrp/i18n/fr_FR.csv delete mode 100644 app/code/Magento/Msrp/i18n/nl_NL.csv delete mode 100644 app/code/Magento/Msrp/i18n/pt_BR.csv delete mode 100644 app/code/Magento/Msrp/i18n/zh_Hans_CN.csv delete mode 100644 app/code/Magento/ProductVideo/i18n/de_DE.csv delete mode 100644 app/code/Magento/ProductVideo/i18n/es_ES.csv delete mode 100644 app/code/Magento/ProductVideo/i18n/fr_FR.csv delete mode 100644 app/code/Magento/ProductVideo/i18n/nl_NL.csv delete mode 100644 app/code/Magento/ProductVideo/i18n/pt_BR.csv delete mode 100644 app/code/Magento/ProductVideo/i18n/zh_Hans_CN.csv delete mode 100644 app/code/Magento/Search/i18n/de_DE.csv delete mode 100644 app/code/Magento/Search/i18n/es_ES.csv delete mode 100644 app/code/Magento/Search/i18n/fr_FR.csv delete mode 100644 app/code/Magento/Search/i18n/nl_NL.csv delete mode 100644 app/code/Magento/Search/i18n/pt_BR.csv delete mode 100644 app/code/Magento/Search/i18n/zh_Hans_CN.csv delete mode 100644 app/code/Magento/Swatches/i18n/de_DE.csv delete mode 100644 app/code/Magento/Swatches/i18n/es_ES.csv delete mode 100644 app/code/Magento/Swatches/i18n/fr_FR.csv delete mode 100644 app/code/Magento/Swatches/i18n/nl_NL.csv delete mode 100644 app/code/Magento/Swatches/i18n/pt_BR.csv delete mode 100644 app/code/Magento/Swatches/i18n/zh_Hans_CN.csv delete mode 100644 app/code/Magento/Ui/i18n/de_DE.csv delete mode 100644 app/code/Magento/Ui/i18n/es_ES.csv delete mode 100644 app/code/Magento/Ui/i18n/fr_FR.csv delete mode 100644 app/code/Magento/Ui/i18n/nl_NL.csv delete mode 100644 app/code/Magento/Ui/i18n/pt_BR.csv delete mode 100644 app/code/Magento/Ui/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/Developer/i18n/de_DE.csv b/app/code/Magento/Developer/i18n/de_DE.csv deleted file mode 100644 index e9c858101b71c..0000000000000 --- a/app/code/Magento/Developer/i18n/de_DE.csv +++ /dev/null @@ -1,5 +0,0 @@ -"Front-end development workflow","Front-end development workflow" -"Workflow type","Workflow type" -"Server side less compilation","Server side less compilation" -"Client side less compilation","Client side less compilation" -"Not available in production mode","Not available in production mode" diff --git a/app/code/Magento/Developer/i18n/es_ES.csv b/app/code/Magento/Developer/i18n/es_ES.csv deleted file mode 100644 index e9c858101b71c..0000000000000 --- a/app/code/Magento/Developer/i18n/es_ES.csv +++ /dev/null @@ -1,5 +0,0 @@ -"Front-end development workflow","Front-end development workflow" -"Workflow type","Workflow type" -"Server side less compilation","Server side less compilation" -"Client side less compilation","Client side less compilation" -"Not available in production mode","Not available in production mode" diff --git a/app/code/Magento/Developer/i18n/fr_FR.csv b/app/code/Magento/Developer/i18n/fr_FR.csv deleted file mode 100644 index e9c858101b71c..0000000000000 --- a/app/code/Magento/Developer/i18n/fr_FR.csv +++ /dev/null @@ -1,5 +0,0 @@ -"Front-end development workflow","Front-end development workflow" -"Workflow type","Workflow type" -"Server side less compilation","Server side less compilation" -"Client side less compilation","Client side less compilation" -"Not available in production mode","Not available in production mode" diff --git a/app/code/Magento/Developer/i18n/nl_NL.csv b/app/code/Magento/Developer/i18n/nl_NL.csv deleted file mode 100644 index e9c858101b71c..0000000000000 --- a/app/code/Magento/Developer/i18n/nl_NL.csv +++ /dev/null @@ -1,5 +0,0 @@ -"Front-end development workflow","Front-end development workflow" -"Workflow type","Workflow type" -"Server side less compilation","Server side less compilation" -"Client side less compilation","Client side less compilation" -"Not available in production mode","Not available in production mode" diff --git a/app/code/Magento/Developer/i18n/pt_BR.csv b/app/code/Magento/Developer/i18n/pt_BR.csv deleted file mode 100644 index e9c858101b71c..0000000000000 --- a/app/code/Magento/Developer/i18n/pt_BR.csv +++ /dev/null @@ -1,5 +0,0 @@ -"Front-end development workflow","Front-end development workflow" -"Workflow type","Workflow type" -"Server side less compilation","Server side less compilation" -"Client side less compilation","Client side less compilation" -"Not available in production mode","Not available in production mode" diff --git a/app/code/Magento/Developer/i18n/zh_Hans_CN.csv b/app/code/Magento/Developer/i18n/zh_Hans_CN.csv deleted file mode 100644 index e9c858101b71c..0000000000000 --- a/app/code/Magento/Developer/i18n/zh_Hans_CN.csv +++ /dev/null @@ -1,5 +0,0 @@ -"Front-end development workflow","Front-end development workflow" -"Workflow type","Workflow type" -"Server side less compilation","Server side less compilation" -"Client side less compilation","Client side less compilation" -"Not available in production mode","Not available in production mode" diff --git a/app/code/Magento/Msrp/i18n/de_DE.csv b/app/code/Magento/Msrp/i18n/de_DE.csv deleted file mode 100644 index be8e733a4bfd1..0000000000000 --- a/app/code/Magento/Msrp/i18n/de_DE.csv +++ /dev/null @@ -1,2 +0,0 @@ -"Enabling MAP by default will hide all product prices on Storefront.","Enabling MAP by default will hide all product prices on Storefront." -"Warning!","Warning!" diff --git a/app/code/Magento/Msrp/i18n/es_ES.csv b/app/code/Magento/Msrp/i18n/es_ES.csv deleted file mode 100644 index be8e733a4bfd1..0000000000000 --- a/app/code/Magento/Msrp/i18n/es_ES.csv +++ /dev/null @@ -1,2 +0,0 @@ -"Enabling MAP by default will hide all product prices on Storefront.","Enabling MAP by default will hide all product prices on Storefront." -"Warning!","Warning!" diff --git a/app/code/Magento/Msrp/i18n/fr_FR.csv b/app/code/Magento/Msrp/i18n/fr_FR.csv deleted file mode 100644 index be8e733a4bfd1..0000000000000 --- a/app/code/Magento/Msrp/i18n/fr_FR.csv +++ /dev/null @@ -1,2 +0,0 @@ -"Enabling MAP by default will hide all product prices on Storefront.","Enabling MAP by default will hide all product prices on Storefront." -"Warning!","Warning!" diff --git a/app/code/Magento/Msrp/i18n/nl_NL.csv b/app/code/Magento/Msrp/i18n/nl_NL.csv deleted file mode 100644 index be8e733a4bfd1..0000000000000 --- a/app/code/Magento/Msrp/i18n/nl_NL.csv +++ /dev/null @@ -1,2 +0,0 @@ -"Enabling MAP by default will hide all product prices on Storefront.","Enabling MAP by default will hide all product prices on Storefront." -"Warning!","Warning!" diff --git a/app/code/Magento/Msrp/i18n/pt_BR.csv b/app/code/Magento/Msrp/i18n/pt_BR.csv deleted file mode 100644 index be8e733a4bfd1..0000000000000 --- a/app/code/Magento/Msrp/i18n/pt_BR.csv +++ /dev/null @@ -1,2 +0,0 @@ -"Enabling MAP by default will hide all product prices on Storefront.","Enabling MAP by default will hide all product prices on Storefront." -"Warning!","Warning!" diff --git a/app/code/Magento/Msrp/i18n/zh_Hans_CN.csv b/app/code/Magento/Msrp/i18n/zh_Hans_CN.csv deleted file mode 100644 index be8e733a4bfd1..0000000000000 --- a/app/code/Magento/Msrp/i18n/zh_Hans_CN.csv +++ /dev/null @@ -1,2 +0,0 @@ -"Enabling MAP by default will hide all product prices on Storefront.","Enabling MAP by default will hide all product prices on Storefront." -"Warning!","Warning!" diff --git a/app/code/Magento/ProductVideo/i18n/de_DE.csv b/app/code/Magento/ProductVideo/i18n/de_DE.csv deleted file mode 100644 index ca24668bb8d16..0000000000000 --- a/app/code/Magento/ProductVideo/i18n/de_DE.csv +++ /dev/null @@ -1,10 +0,0 @@ -"Add video","Add video" -"New Video","New Video" -"Product Video","Product Video" -"YouTube API key","YouTube API key" -"You have not entered youtube API key. No information about youtube video will be retrieved.","You have not entered youtube API key. No information about youtube video will be retrieved." -"Url","Url" -"Preview Image","Preview Image" -"Get Video Information","Get Video Information" -"Youtube or Vimeo supported","Youtube or Vimeo supported" -"Delete image in all store views","Delete image in all store views" diff --git a/app/code/Magento/ProductVideo/i18n/es_ES.csv b/app/code/Magento/ProductVideo/i18n/es_ES.csv deleted file mode 100644 index ca24668bb8d16..0000000000000 --- a/app/code/Magento/ProductVideo/i18n/es_ES.csv +++ /dev/null @@ -1,10 +0,0 @@ -"Add video","Add video" -"New Video","New Video" -"Product Video","Product Video" -"YouTube API key","YouTube API key" -"You have not entered youtube API key. No information about youtube video will be retrieved.","You have not entered youtube API key. No information about youtube video will be retrieved." -"Url","Url" -"Preview Image","Preview Image" -"Get Video Information","Get Video Information" -"Youtube or Vimeo supported","Youtube or Vimeo supported" -"Delete image in all store views","Delete image in all store views" diff --git a/app/code/Magento/ProductVideo/i18n/fr_FR.csv b/app/code/Magento/ProductVideo/i18n/fr_FR.csv deleted file mode 100644 index ca24668bb8d16..0000000000000 --- a/app/code/Magento/ProductVideo/i18n/fr_FR.csv +++ /dev/null @@ -1,10 +0,0 @@ -"Add video","Add video" -"New Video","New Video" -"Product Video","Product Video" -"YouTube API key","YouTube API key" -"You have not entered youtube API key. No information about youtube video will be retrieved.","You have not entered youtube API key. No information about youtube video will be retrieved." -"Url","Url" -"Preview Image","Preview Image" -"Get Video Information","Get Video Information" -"Youtube or Vimeo supported","Youtube or Vimeo supported" -"Delete image in all store views","Delete image in all store views" diff --git a/app/code/Magento/ProductVideo/i18n/nl_NL.csv b/app/code/Magento/ProductVideo/i18n/nl_NL.csv deleted file mode 100644 index 5ad8386573040..0000000000000 --- a/app/code/Magento/ProductVideo/i18n/nl_NL.csv +++ /dev/null @@ -1,10 +0,0 @@ -"Add video","Add video" -"New Video","New Video" -"Product Video","Product Video" -"YouTube API key","YouTube API key" -"You have not entered youtube API key. No information about youtube video will be retrieved.","You have not entered youtube API key. No information about youtube video will be retrieved." -"Url","Url" -"Preview Image","Preview Image" -"Get Video Information","Get Video Information" -"Youtube or Vimeo supported","Youtube or Vimeo supported" -"Delete image in all store views","Delete image in all store views" \ No newline at end of file diff --git a/app/code/Magento/ProductVideo/i18n/pt_BR.csv b/app/code/Magento/ProductVideo/i18n/pt_BR.csv deleted file mode 100644 index 5ad8386573040..0000000000000 --- a/app/code/Magento/ProductVideo/i18n/pt_BR.csv +++ /dev/null @@ -1,10 +0,0 @@ -"Add video","Add video" -"New Video","New Video" -"Product Video","Product Video" -"YouTube API key","YouTube API key" -"You have not entered youtube API key. No information about youtube video will be retrieved.","You have not entered youtube API key. No information about youtube video will be retrieved." -"Url","Url" -"Preview Image","Preview Image" -"Get Video Information","Get Video Information" -"Youtube or Vimeo supported","Youtube or Vimeo supported" -"Delete image in all store views","Delete image in all store views" \ No newline at end of file diff --git a/app/code/Magento/ProductVideo/i18n/zh_Hans_CN.csv b/app/code/Magento/ProductVideo/i18n/zh_Hans_CN.csv deleted file mode 100644 index 5ad8386573040..0000000000000 --- a/app/code/Magento/ProductVideo/i18n/zh_Hans_CN.csv +++ /dev/null @@ -1,10 +0,0 @@ -"Add video","Add video" -"New Video","New Video" -"Product Video","Product Video" -"YouTube API key","YouTube API key" -"You have not entered youtube API key. No information about youtube video will be retrieved.","You have not entered youtube API key. No information about youtube video will be retrieved." -"Url","Url" -"Preview Image","Preview Image" -"Get Video Information","Get Video Information" -"Youtube or Vimeo supported","Youtube or Vimeo supported" -"Delete image in all store views","Delete image in all store views" \ No newline at end of file diff --git a/app/code/Magento/Search/i18n/de_DE.csv b/app/code/Magento/Search/i18n/de_DE.csv deleted file mode 100644 index 8b4b04aa3b9ec..0000000000000 --- a/app/code/Magento/Search/i18n/de_DE.csv +++ /dev/null @@ -1 +0,0 @@ -"Search Engine","Search Engine" diff --git a/app/code/Magento/Search/i18n/es_ES.csv b/app/code/Magento/Search/i18n/es_ES.csv deleted file mode 100644 index 8b4b04aa3b9ec..0000000000000 --- a/app/code/Magento/Search/i18n/es_ES.csv +++ /dev/null @@ -1 +0,0 @@ -"Search Engine","Search Engine" diff --git a/app/code/Magento/Search/i18n/fr_FR.csv b/app/code/Magento/Search/i18n/fr_FR.csv deleted file mode 100644 index 8b4b04aa3b9ec..0000000000000 --- a/app/code/Magento/Search/i18n/fr_FR.csv +++ /dev/null @@ -1 +0,0 @@ -"Search Engine","Search Engine" diff --git a/app/code/Magento/Search/i18n/nl_NL.csv b/app/code/Magento/Search/i18n/nl_NL.csv deleted file mode 100644 index 8b4b04aa3b9ec..0000000000000 --- a/app/code/Magento/Search/i18n/nl_NL.csv +++ /dev/null @@ -1 +0,0 @@ -"Search Engine","Search Engine" diff --git a/app/code/Magento/Search/i18n/pt_BR.csv b/app/code/Magento/Search/i18n/pt_BR.csv deleted file mode 100644 index c10566a7c9800..0000000000000 --- a/app/code/Magento/Search/i18n/pt_BR.csv +++ /dev/null @@ -1 +0,0 @@ -"Search Engine","Mecanismo de Busca" diff --git a/app/code/Magento/Search/i18n/zh_Hans_CN.csv b/app/code/Magento/Search/i18n/zh_Hans_CN.csv deleted file mode 100644 index 8b4b04aa3b9ec..0000000000000 --- a/app/code/Magento/Search/i18n/zh_Hans_CN.csv +++ /dev/null @@ -1 +0,0 @@ -"Search Engine","Search Engine" diff --git a/app/code/Magento/Swatches/i18n/de_DE.csv b/app/code/Magento/Swatches/i18n/de_DE.csv deleted file mode 100644 index f0aa34bbef26e..0000000000000 --- a/app/code/Magento/Swatches/i18n/de_DE.csv +++ /dev/null @@ -1,2 +0,0 @@ -"Swatch","Swatch" -"Swatches per Product","Swatches per Product" diff --git a/app/code/Magento/Swatches/i18n/es_ES.csv b/app/code/Magento/Swatches/i18n/es_ES.csv deleted file mode 100644 index f0aa34bbef26e..0000000000000 --- a/app/code/Magento/Swatches/i18n/es_ES.csv +++ /dev/null @@ -1,2 +0,0 @@ -"Swatch","Swatch" -"Swatches per Product","Swatches per Product" diff --git a/app/code/Magento/Swatches/i18n/fr_FR.csv b/app/code/Magento/Swatches/i18n/fr_FR.csv deleted file mode 100644 index f0aa34bbef26e..0000000000000 --- a/app/code/Magento/Swatches/i18n/fr_FR.csv +++ /dev/null @@ -1,2 +0,0 @@ -"Swatch","Swatch" -"Swatches per Product","Swatches per Product" diff --git a/app/code/Magento/Swatches/i18n/nl_NL.csv b/app/code/Magento/Swatches/i18n/nl_NL.csv deleted file mode 100644 index f0aa34bbef26e..0000000000000 --- a/app/code/Magento/Swatches/i18n/nl_NL.csv +++ /dev/null @@ -1,2 +0,0 @@ -"Swatch","Swatch" -"Swatches per Product","Swatches per Product" diff --git a/app/code/Magento/Swatches/i18n/pt_BR.csv b/app/code/Magento/Swatches/i18n/pt_BR.csv deleted file mode 100644 index f0aa34bbef26e..0000000000000 --- a/app/code/Magento/Swatches/i18n/pt_BR.csv +++ /dev/null @@ -1,2 +0,0 @@ -"Swatch","Swatch" -"Swatches per Product","Swatches per Product" diff --git a/app/code/Magento/Swatches/i18n/zh_Hans_CN.csv b/app/code/Magento/Swatches/i18n/zh_Hans_CN.csv deleted file mode 100644 index f0aa34bbef26e..0000000000000 --- a/app/code/Magento/Swatches/i18n/zh_Hans_CN.csv +++ /dev/null @@ -1,2 +0,0 @@ -"Swatch","Swatch" -"Swatches per Product","Swatches per Product" diff --git a/app/code/Magento/Ui/i18n/de_DE.csv b/app/code/Magento/Ui/i18n/de_DE.csv deleted file mode 100644 index 2efac126b857c..0000000000000 --- a/app/code/Magento/Ui/i18n/de_DE.csv +++ /dev/null @@ -1,4 +0,0 @@ -"Log JS Errors to Session Storage","Log JS Errors to Session Storage" -"If enabled, can be used by functional tests for extended reporting","If enabled, can be used by functional tests for extended reporting" -"Log JS Errors to Session Storage Key","Log JS Errors to Session Storage Key" -"Use this key to retrieve collected js errors","Use this key to retrieve collected js errors" diff --git a/app/code/Magento/Ui/i18n/es_ES.csv b/app/code/Magento/Ui/i18n/es_ES.csv deleted file mode 100644 index 2efac126b857c..0000000000000 --- a/app/code/Magento/Ui/i18n/es_ES.csv +++ /dev/null @@ -1,4 +0,0 @@ -"Log JS Errors to Session Storage","Log JS Errors to Session Storage" -"If enabled, can be used by functional tests for extended reporting","If enabled, can be used by functional tests for extended reporting" -"Log JS Errors to Session Storage Key","Log JS Errors to Session Storage Key" -"Use this key to retrieve collected js errors","Use this key to retrieve collected js errors" diff --git a/app/code/Magento/Ui/i18n/fr_FR.csv b/app/code/Magento/Ui/i18n/fr_FR.csv deleted file mode 100644 index 2efac126b857c..0000000000000 --- a/app/code/Magento/Ui/i18n/fr_FR.csv +++ /dev/null @@ -1,4 +0,0 @@ -"Log JS Errors to Session Storage","Log JS Errors to Session Storage" -"If enabled, can be used by functional tests for extended reporting","If enabled, can be used by functional tests for extended reporting" -"Log JS Errors to Session Storage Key","Log JS Errors to Session Storage Key" -"Use this key to retrieve collected js errors","Use this key to retrieve collected js errors" diff --git a/app/code/Magento/Ui/i18n/nl_NL.csv b/app/code/Magento/Ui/i18n/nl_NL.csv deleted file mode 100644 index 2efac126b857c..0000000000000 --- a/app/code/Magento/Ui/i18n/nl_NL.csv +++ /dev/null @@ -1,4 +0,0 @@ -"Log JS Errors to Session Storage","Log JS Errors to Session Storage" -"If enabled, can be used by functional tests for extended reporting","If enabled, can be used by functional tests for extended reporting" -"Log JS Errors to Session Storage Key","Log JS Errors to Session Storage Key" -"Use this key to retrieve collected js errors","Use this key to retrieve collected js errors" diff --git a/app/code/Magento/Ui/i18n/pt_BR.csv b/app/code/Magento/Ui/i18n/pt_BR.csv deleted file mode 100644 index 2efac126b857c..0000000000000 --- a/app/code/Magento/Ui/i18n/pt_BR.csv +++ /dev/null @@ -1,4 +0,0 @@ -"Log JS Errors to Session Storage","Log JS Errors to Session Storage" -"If enabled, can be used by functional tests for extended reporting","If enabled, can be used by functional tests for extended reporting" -"Log JS Errors to Session Storage Key","Log JS Errors to Session Storage Key" -"Use this key to retrieve collected js errors","Use this key to retrieve collected js errors" diff --git a/app/code/Magento/Ui/i18n/zh_Hans_CN.csv b/app/code/Magento/Ui/i18n/zh_Hans_CN.csv deleted file mode 100644 index 2efac126b857c..0000000000000 --- a/app/code/Magento/Ui/i18n/zh_Hans_CN.csv +++ /dev/null @@ -1,4 +0,0 @@ -"Log JS Errors to Session Storage","Log JS Errors to Session Storage" -"If enabled, can be used by functional tests for extended reporting","If enabled, can be used by functional tests for extended reporting" -"Log JS Errors to Session Storage Key","Log JS Errors to Session Storage Key" -"Use this key to retrieve collected js errors","Use this key to retrieve collected js errors" From 2e0a846b0b0d3bdcac0786ed7e91eaf96c0d501e Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Mon, 25 Mar 2019 22:31:45 +0200 Subject: [PATCH 076/142] unit test fix --- .../Framework/Event/Test/Unit/Invoker/InvokerDefaultTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 82e660913ddc1..b339ed55bf691 100644 --- a/lib/internal/Magento/Framework/Event/Test/Unit/Invoker/InvokerDefaultTest.php +++ b/lib/internal/Magento/Framework/Event/Test/Unit/Invoker/InvokerDefaultTest.php @@ -173,7 +173,7 @@ public function testWrongInterfaceCallWithDisabledDeveloperMode($shared) $this->returnValue($notObserver) ); $this->_appStateMock->expects( - $this->exactly(2) + $this->exactly(1) )->method( 'getMode' )->will( From a82bac4ddd85147cc133de51e0cc580e1171aeea Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Tue, 26 Mar 2019 10:48:59 +0300 Subject: [PATCH 077/142] MAGETWO-64838: Unable to create order from store front if customer address custom attribute is required - code refactoring; --- .../Webapi/CustomAttribute/PreprocessorInterface.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php b/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php index 820936abd49ba..8de30e92218c0 100644 --- a/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php +++ b/lib/internal/Magento/Framework/Webapi/CustomAttribute/PreprocessorInterface.php @@ -17,7 +17,7 @@ interface PreprocessorInterface * @param mixed $attribute * @return bool */ - public function shouldBeProcessed($key, $attribute); + public function shouldBeProcessed(string $key, $attribute): bool; /** * Process attribute object according to type rules @@ -25,12 +25,12 @@ public function shouldBeProcessed($key, $attribute); * @param string $key * @param mixed $attribute */ - public function process($key, &$attribute); + public function process(string $key, &$attribute); /** * Get list of affected attributes for the current preprocessor * * @return array */ - public function getAffectedAttributes(); + public function getAffectedAttributes(): array; } From b78c229577b10b0b0334ba7ede392a556382f509 Mon Sep 17 00:00:00 2001 From: Lusine Papyan <Lusine_Papyan@epam.com> Date: Mon, 25 Feb 2019 14:58:11 +0400 Subject: [PATCH 078/142] MAGETWO-70232: Import customizable options adds it to another product if same SKU is filled - Add automated test script --- .../ActionGroup/CustomOptionsActionGroup.xml | 52 ++++++++++++ ...AdminProductCustomizableOptionsSection.xml | 12 ++- ...CustomizableOptionToProductWithSKUTest.xml | 84 +++++++++++++++++++ 3 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CustomOptionsActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CustomOptionsActionGroup.xml index 2d966dde64c4a..b372166f1d0de 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CustomOptionsActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CustomOptionsActionGroup.xml @@ -52,4 +52,56 @@ <selectOption selector="{{AdminProductCustomizableOptionsSection.optionPriceType('0')}}" userInput="{{option.price_type}}" stepKey="selectPriceType"/> <fillField selector="{{AdminProductCustomizableOptionsSection.optionFileExtensions('0')}}" userInput="{{option.file_extension}}" stepKey="fillCompatibleExtensions"/> </actionGroup> + + <actionGroup name="AddProductCustomOptionField"> + <arguments> + <argument name="option" defaultValue="ProductOptionField"/> + <argiment name="optionIndex" type="string"/> + </arguments> + <conditionalClick selector="{{AdminProductCustomizableOptionsSection.customizableOptions}}" dependentSelector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}" visible="false" stepKey="openCustomOptionSection"/> + <click selector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}" stepKey="clickAddOption"/> + <waitForElementVisible selector="{{AdminProductCustomizableOptionsSection.lastOptionTitle}}" stepKey="waitForOption"/> + <fillField selector="{{AdminProductCustomizableOptionsSection.lastOptionTitle}}" userInput="{{option.title}}" stepKey="fillTitle"/> + <click selector="{{AdminProductCustomizableOptionsSection.lastOptionTypeParent}}" stepKey="openTypeSelect"/> + <click selector="{{AdminProductCustomizableOptionsSection.optionType('Field')}}" stepKey="selectTypeFile"/> + <waitForElementVisible selector="{{AdminProductCustomizableOptionsSection.optionPrice(optionIndex)}}" stepKey="waitForElements"/> + <fillField selector="{{AdminProductCustomizableOptionsSection.optionPrice(optionIndex)}}" userInput="{{option.price}}" stepKey="fillPrice"/> + <selectOption selector="{{AdminProductCustomizableOptionsSection.optionPriceType(optionIndex)}}" userInput="{{option.price_type}}" stepKey="selectPriceType"/> + <fillField selector="{{AdminProductCustomizableOptionsSection.optionSku(optionIndex)}}" userInput="{{option.title}}" stepKey="fillSku"/> + </actionGroup> + + <actionGroup name="importProductCustomizableOptions"> + <arguments> + <argument name="productName" type="string"/> + </arguments> + <click selector="{{AdminProductCustomizableOptionsSection.importOptions}}" stepKey="clickImportOptions"/> + <waitForElementVisible selector="{{AdminProductImportOptionsSection.selectProductTitle}}" stepKey="waitForTitleVisible"/> + <conditionalClick selector="{{AdminProductImportOptionsSection.resetFiltersButton}}" dependentSelector="{{AdminProductImportOptionsSection.resetFiltersButton}}" visible="true" stepKey="clickResetFilters"/> + <click selector="{{AdminProductImportOptionsSection.filterButton}}" stepKey="clickFilterButton"/> + <waitForElementVisible selector="{{AdminProductImportOptionsSection.nameField}}" stepKey="waitForNameField"/> + <fillField selector="{{AdminProductImportOptionsSection.nameField}}" userInput="{{productName}}" stepKey="fillProductName"/> + <click selector="{{AdminProductImportOptionsSection.applyFiltersButton}}" stepKey="clickApplyFilters"/> + <checkOption selector="{{AdminProductImportOptionsSection.firstRowItemCheckbox}}" stepKey="checkProductCheckbox"/> + <click selector="{{AdminProductImportOptionsSection.importButton}}" stepKey="clickImport"/> + </actionGroup> + + <actionGroup name="resetImportOptionFilter"> + <conditionalClick selector="{{AdminProductCustomizableOptionsSection.customizableOptions}}" dependentSelector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}" visible="false" stepKey="openCustomOptionSection"/> + <click selector="{{AdminProductCustomizableOptionsSection.importOptions}}" stepKey="clickImportOptions"/> + <click selector="{{AdminProductImportOptionsSection.resetFiltersButton}}" stepKey="clickResetFilterButton"/> + </actionGroup> + + <actionGroup name="checkCustomizableOptionImport"> + <arguments> + <argument name="option" defaultValue="ProductOptionField"/> + <argiment name="optionIndex" type="string"/> + </arguments> + <grabValueFrom selector="{{AdminProductCustomizableOptionsSection.optionTitleInput(optionIndex)}}" stepKey="grabOptionTitle"/> + <grabValueFrom selector="{{AdminProductCustomizableOptionsSection.optionPrice(optionIndex)}}" stepKey="grabOptionPrice"/> + <grabValueFrom selector="{{AdminProductCustomizableOptionsSection.optionSku(optionIndex)}}" stepKey="grabOptionSku"/> + + <assertEquals expected="{{option.title}}" expectedType="string" actual="$grabOptionTitle" stepKey="assertOptionTitle"/> + <assertEquals expected="{{option.price}}" expectedType="string" actual="$grabOptionPrice" stepKey="assertOptionPrice"/> + <assertEquals expected="{{option.title}}" expectedType="string" actual="$grabOptionSku" stepKey="assertOptionSku"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml index fc78c25ec49fa..5598edcfbcb28 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml @@ -45,5 +45,15 @@ <element name="optionPriceType" type="select" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr//*[@name='product[options][{{var}}][price_type]']" parameterized="true"/> <element name="optionSku" type="input" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr//*[@name='product[options][{{index}}][sku]']" parameterized="true"/> <element name="optionFileExtensions" type="input" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr//*[@name='product[options][{{index}}][file_extension]']" parameterized="true"/> + <element name="importOptions" type="button" selector="//button[@data-index='button_import']" timeout="30"/> </section> -</sections> \ No newline at end of file + <section name="AdminProductImportOptionsSection"> + <element name="selectProductTitle" type="text" selector="//h1[contains(text(), 'Select Product')]" timeout="30"/> + <element name="filterButton" type="button" selector="//button[@data-action='grid-filter-expand']" timeout="30"/> + <element name="nameField" type="input" selector="//input[@name='name']" timeout="30"/> + <element name="applyFiltersButton" type="button" selector="//button[@data-action='grid-filter-apply']" timeout="30"/> + <element name="resetFiltersButton" type="button" selector="//button[@data-action='grid-filter-reset']" timeout="30"/> + <element name="firstRowItemCheckbox" type="input" selector="//input[@data-action='select-row']" timeout="30"/> + <element name="importButton" type="button" selector="//button[@class='action-primary']/span[contains(text(), 'Import')]" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml new file mode 100644 index 0000000000000..836c07a7c1935 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.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="AdminImportCustomizableOptionToProductWithSKUTest"> + <annotations> + <features value="Catalog"/> + <title value="Check that 'trie price' block not available for simple product from options without 'trie price'"/> + <description value="Check that 'trie price' block not available for simple product from options without 'trie price'"/> + <severity value="MAJOR"/> + <testCaseId value="MAGETWO-98211"/> + <useCaseId value="MAGETWO-70232"/> + <group value="catalog"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!--Create category--> + <createData entity="ApiCategory" stepKey="createCategory"/> + + <!-- Create two product --> + <createData entity="SimpleProduct2" stepKey="createFirstProduct"/> + <createData entity="ApiSimpleProduct" stepKey="createSecondProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + + </before> + <after> + + <!--Delete second product with changed sku--> + <actionGroup ref="deleteProductBySku" stepKey="deleteSecondProduct"> + <argument name="sku" value="$$createFirstProduct.sku$$-1"/> + </actionGroup> + + <!--Delete created data--> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createFirstProduct" stepKey="deleteFirstProduct"/> + + <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + </after> + + <!--Go to product page --> + <amOnPage url="{{AdminProductEditPage.url($$createFirstProduct.id$$)}}" stepKey="goToProductEditPage"/> + <waitForPageLoad stepKey="waitForProductEditPageLoad"/> + <actionGroup ref="AddProductCustomOptionField" stepKey="addCutomOption1"> + <argument name="option" value="ProductOptionField"/> + <argument name="optionIndex" value="0"/> + </actionGroup> + <actionGroup ref="AddProductCustomOptionField" stepKey="addCutomOption2"> + <argument name="option" value="ProductOptionField2"/> + <argument name="optionIndex" value="1"/> + </actionGroup> + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + + <!--Change second product sku to first product sku--> + <amOnPage url="{{AdminProductEditPage.url($$createSecondProduct.id$$)}}" stepKey="goToProductEditPage1"/> + <waitForPageLoad stepKey="waitForProductEditPageLoad1"/> + <fillField selector="{{AdminProductFormSection.productSku}}" userInput="$$createFirstProduct.sku$$" stepKey="fillProductSku1"/> + + <!--Import customizable options and check--> + <conditionalClick selector="{{AdminProductCustomizableOptionsSection.customizableOptions}}" dependentSelector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}" visible="false" stepKey="openCustomOptionSection"/> + <actionGroup ref="importProductCustomizableOptions" stepKey="importOptions"> + <argument name="productName" value="$$createFirstProduct.name$$"/> + </actionGroup> + <actionGroup ref="checkCustomizableOptionImport" stepKey="checkFirstOptionImport"> + <argument name="option" value="ProductOptionField"/> + <argument name="optionIndex" value="0"/> + </actionGroup> + <actionGroup ref="checkCustomizableOptionImport" stepKey="checkSecondOptionImport"> + <argument name="option" value="ProductOptionField2"/> + <argument name="optionIndex" value="1"/> + </actionGroup> + + <!--SAve product and check sku changed message--> + <actionGroup ref="saveProductForm" stepKey="saveProduct1"/> + <see userInput="SKU for product $$createSecondProduct.name$$ has been changed to $$createFirstProduct.sku$$-1." stepKey="seeSkuChangedMessage"/> + </test> +</tests> From fc94ab8d0c1df4654a92b9817bc47f5ff7dce802 Mon Sep 17 00:00:00 2001 From: Lusine Papyan <Lusine_Papyan@epam.com> Date: Mon, 25 Mar 2019 18:59:26 +0400 Subject: [PATCH 079/142] MAGETWO-70232: Import customizable options adds it to another product if same SKU is filled - Update automated test script --- .../ActionGroup/CustomOptionsActionGroup.xml | 5 ---- ...AdminProductCustomizableOptionsSection.xml | 2 +- ...CustomizableOptionToProductWithSKUTest.xml | 26 +++++++++---------- ...eForProductOptionsWithoutTierPriceTest.xml | 4 +-- 4 files changed, 15 insertions(+), 22 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CustomOptionsActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CustomOptionsActionGroup.xml index b372166f1d0de..b914d5e20712d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CustomOptionsActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CustomOptionsActionGroup.xml @@ -52,7 +52,6 @@ <selectOption selector="{{AdminProductCustomizableOptionsSection.optionPriceType('0')}}" userInput="{{option.price_type}}" stepKey="selectPriceType"/> <fillField selector="{{AdminProductCustomizableOptionsSection.optionFileExtensions('0')}}" userInput="{{option.file_extension}}" stepKey="fillCompatibleExtensions"/> </actionGroup> - <actionGroup name="AddProductCustomOptionField"> <arguments> <argument name="option" defaultValue="ProductOptionField"/> @@ -69,7 +68,6 @@ <selectOption selector="{{AdminProductCustomizableOptionsSection.optionPriceType(optionIndex)}}" userInput="{{option.price_type}}" stepKey="selectPriceType"/> <fillField selector="{{AdminProductCustomizableOptionsSection.optionSku(optionIndex)}}" userInput="{{option.title}}" stepKey="fillSku"/> </actionGroup> - <actionGroup name="importProductCustomizableOptions"> <arguments> <argument name="productName" type="string"/> @@ -84,13 +82,11 @@ <checkOption selector="{{AdminProductImportOptionsSection.firstRowItemCheckbox}}" stepKey="checkProductCheckbox"/> <click selector="{{AdminProductImportOptionsSection.importButton}}" stepKey="clickImport"/> </actionGroup> - <actionGroup name="resetImportOptionFilter"> <conditionalClick selector="{{AdminProductCustomizableOptionsSection.customizableOptions}}" dependentSelector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}" visible="false" stepKey="openCustomOptionSection"/> <click selector="{{AdminProductCustomizableOptionsSection.importOptions}}" stepKey="clickImportOptions"/> <click selector="{{AdminProductImportOptionsSection.resetFiltersButton}}" stepKey="clickResetFilterButton"/> </actionGroup> - <actionGroup name="checkCustomizableOptionImport"> <arguments> <argument name="option" defaultValue="ProductOptionField"/> @@ -99,7 +95,6 @@ <grabValueFrom selector="{{AdminProductCustomizableOptionsSection.optionTitleInput(optionIndex)}}" stepKey="grabOptionTitle"/> <grabValueFrom selector="{{AdminProductCustomizableOptionsSection.optionPrice(optionIndex)}}" stepKey="grabOptionPrice"/> <grabValueFrom selector="{{AdminProductCustomizableOptionsSection.optionSku(optionIndex)}}" stepKey="grabOptionSku"/> - <assertEquals expected="{{option.title}}" expectedType="string" actual="$grabOptionTitle" stepKey="assertOptionTitle"/> <assertEquals expected="{{option.price}}" expectedType="string" actual="$grabOptionPrice" stepKey="assertOptionPrice"/> <assertEquals expected="{{option.title}}" expectedType="string" actual="$grabOptionSku" stepKey="assertOptionSku"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml index 5598edcfbcb28..352d219351fb8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml @@ -54,6 +54,6 @@ <element name="applyFiltersButton" type="button" selector="//button[@data-action='grid-filter-apply']" timeout="30"/> <element name="resetFiltersButton" type="button" selector="//button[@data-action='grid-filter-reset']" timeout="30"/> <element name="firstRowItemCheckbox" type="input" selector="//input[@data-action='select-row']" timeout="30"/> - <element name="importButton" type="button" selector="//button[@class='action-primary']/span[contains(text(), 'Import')]" timeout="30"/> + <element name="importButton" type="button" selector="//button[contains(@class, 'action-primary')]/span[contains(text(), 'Import')]" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml index 836c07a7c1935..79ff7bcade77b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml @@ -11,8 +11,8 @@ <test name="AdminImportCustomizableOptionToProductWithSKUTest"> <annotations> <features value="Catalog"/> - <title value="Check that 'trie price' block not available for simple product from options without 'trie price'"/> - <description value="Check that 'trie price' block not available for simple product from options without 'trie price'"/> + <title value="Import customizable options to a product with existing SKU"/> + <description value="Import customizable options to a product with existing SKU"/> <severity value="MAJOR"/> <testCaseId value="MAGETWO-98211"/> <useCaseId value="MAGETWO-70232"/> @@ -20,32 +20,30 @@ </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <!--Create category--> + <comment userInput="Create category" stepKey="commentCreateCategory"/> <createData entity="ApiCategory" stepKey="createCategory"/> - <!-- Create two product --> + <comment userInput="Create two product" stepKey="commentCreateTwoProduct"/> <createData entity="SimpleProduct2" stepKey="createFirstProduct"/> <createData entity="ApiSimpleProduct" stepKey="createSecondProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - </before> <after> - - <!--Delete second product with changed sku--> + <!--Delete second product with changed sku--> + <comment userInput="Delete second product with changed sku" stepKey="commentDeleteProduct"/> <actionGroup ref="deleteProductBySku" stepKey="deleteSecondProduct"> <argument name="sku" value="$$createFirstProduct.sku$$-1"/> </actionGroup> - <!--Delete created data--> + <comment userInput="Delete created data" stepKey="commentDeleteCreatedData"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createFirstProduct" stepKey="deleteFirstProduct"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> </after> - <!--Go to product page --> + <comment userInput="Go to product page" stepKey="commentGoToProductPage"/> <amOnPage url="{{AdminProductEditPage.url($$createFirstProduct.id$$)}}" stepKey="goToProductEditPage"/> <waitForPageLoad stepKey="waitForProductEditPageLoad"/> <actionGroup ref="AddProductCustomOptionField" stepKey="addCutomOption1"> @@ -57,13 +55,13 @@ <argument name="optionIndex" value="1"/> </actionGroup> <actionGroup ref="saveProductForm" stepKey="saveProduct"/> - <!--Change second product sku to first product sku--> + <comment userInput="Change second product sku to first product sku" stepKey="commentChangeSecondProduct"/> <amOnPage url="{{AdminProductEditPage.url($$createSecondProduct.id$$)}}" stepKey="goToProductEditPage1"/> <waitForPageLoad stepKey="waitForProductEditPageLoad1"/> <fillField selector="{{AdminProductFormSection.productSku}}" userInput="$$createFirstProduct.sku$$" stepKey="fillProductSku1"/> - <!--Import customizable options and check--> + <comment userInput="Import customizable options and check" stepKey="commentImportOptions"/> <conditionalClick selector="{{AdminProductCustomizableOptionsSection.customizableOptions}}" dependentSelector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}" visible="false" stepKey="openCustomOptionSection"/> <actionGroup ref="importProductCustomizableOptions" stepKey="importOptions"> <argument name="productName" value="$$createFirstProduct.name$$"/> @@ -76,8 +74,8 @@ <argument name="option" value="ProductOptionField2"/> <argument name="optionIndex" value="1"/> </actionGroup> - - <!--SAve product and check sku changed message--> + <!--Save product and check sku changed message--> + <comment userInput="Save product and check sku changed message" stepKey="commentSAveProductAndCheck"/> <actionGroup ref="saveProductForm" stepKey="saveProduct1"/> <see userInput="SKU for product $$createSecondProduct.name$$ has been changed to $$createFirstProduct.sku$$-1." stepKey="seeSkuChangedMessage"/> </test> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml index 3086f4398e08d..51af9d78dfd46 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml @@ -11,8 +11,8 @@ <test name="AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest"> <annotations> <features value="Catalog"/> - <title value="Check that 'trie price' block not available for simple product from options without 'trie price'"/> - <description value="Check that 'trie price' block not available for simple product from options without 'trie price'"/> + <title value="Check that 'tier price' block not available for simple product from options without 'tier price'"/> + <description value="Check that 'tier price' block not available for simple product from options without 'tier price'"/> <severity value="MAJOR"/> <testCaseId value="MAGETWO-97050"/> <useCaseId value="MAGETWO-96842"/> From 203b807ea5d262115a42509c39af64e9a1f2a9b6 Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Tue, 26 Mar 2019 18:21:30 +0530 Subject: [PATCH 080/142] Correct spelling --- .../Magento/Framework/Config/ConfigOptionsListConstants.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php b/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php index 92f0302d93baf..6bdb74ef7b89a 100644 --- a/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php +++ b/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php @@ -47,7 +47,7 @@ class ConfigOptionsListConstants const CONFIG_PATH_SCD_ON_DEMAND_IN_PRODUCTION = 'static_content_on_demand_in_production'; /** - * Paramater for forcing HTML minification even if file is already minified. + * Parameter for forcing HTML minification even if file is already minified. */ const CONFIG_PATH_FORCE_HTML_MINIFICATION = 'force_html_minification'; From 4dcc18aba77d27dd7f284bf4f5421be2cf9a585d Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Tue, 26 Mar 2019 16:01:09 +0200 Subject: [PATCH 081/142] 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 | 27 +++++++++- .../Sales/Block/Adminhtml/TotalsTest.php | 53 +++++++++++++++++++ .../order_with_free_shipping_by_coupon.php | 34 ++++++++++++ ..._with_free_shipping_by_coupon_rollback.php | 8 +++ 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/TotalsTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/order_with_free_shipping_by_coupon.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/order_with_free_shipping_by_coupon_rollback.php diff --git a/app/code/Magento/Sales/Block/Adminhtml/Totals.php b/app/code/Magento/Sales/Block/Adminhtml/Totals.php index 83b155293c2b9..3f08dc48d38d1 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Totals.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Totals.php @@ -5,6 +5,8 @@ */ namespace Magento\Sales\Block\Adminhtml; +use Magento\Sales\Model\Order; + class Totals extends \Magento\Sales\Block\Order\Totals { /** @@ -67,12 +69,16 @@ protected function _initTotals() if (!$this->getSource()->getIsVirtual() && ((double)$this->getSource()->getShippingAmount() || $this->getSource()->getShippingDescription()) ) { + $shippingLabel = __('Shipping & Handling'); + if ($this->isHasFreeShipping($this->getSource()) && $this->getSource()->getDiscountDescription()) { + $shippingLabel .= sprintf(' (%s)', $this->getSource()->getDiscountDescription()); + } $this->_totals['shipping'] = new \Magento\Framework\DataObject( [ 'code' => 'shipping', 'value' => $this->getSource()->getShippingAmount(), 'base_value' => $this->getSource()->getBaseShippingAmount(), - 'label' => __('Shipping & Handling'), + 'label' => $shippingLabel, ] ); } @@ -109,4 +115,23 @@ protected function _initTotals() return $this; } + + /** + * Availability of free shipping in at least one order item + * + * @param Order $order + * @return bool + */ + private function isHasFreeShipping(Order $order): bool + { + $isActive = false; + foreach ($order->getItems() as $orderItem) { + if ($orderItem->getFreeShipping() === '1') { + $isActive = true; + break; + } + } + + return $isActive; + } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/TotalsTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/TotalsTest.php new file mode 100644 index 0000000000000..a77676e64a331 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/TotalsTest.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Block\Adminhtml; + +use Magento\Framework\View\LayoutInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\OrderFactory; + +/** + * Test class for \Magento\Sales\Block\Adminhtml\Totals + */ +class TotalsTest extends \Magento\TestFramework\TestCase\AbstractBackendController +{ + /** @var LayoutInterface */ + protected $_layout; + + /** @var Totals */ + protected $_block; + + /** @var OrderFactory */ + private $orderFactory; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + $this->_layout = $this->_objectManager->get(LayoutInterface::class); + $this->_block = $this->_layout->createBlock(Totals::class, 'totals_block'); + $this->orderFactory = $this->_objectManager->get(OrderFactory::class); + } + + /** + * @magentoDataFixture Magento/Sales/_files/order_with_free_shipping_by_coupon.php + */ + public function testShowShippingCoupon() + { + /** @var Order $order */ + $order = $this->orderFactory->create(); + $order->loadByIncrementId('100000001'); + + $this->_block->setOrder($order); + $this->_block->toHtml(); + + $shippingTotal = $this->_block->getTotal('shipping'); + $this->assertNotFalse($shippingTotal, 'Shipping method is absent on the total\'s block.'); + $this->assertContains('1234567890', $shippingTotal->getLabel(), 'Coupon code is absent in the shipping method label name.'); + } +} 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 new file mode 100644 index 0000000000000..04e39ae3e462c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_free_shipping_by_coupon.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Item as OrderItem; + +require __DIR__ . '/../../../Magento/Sales/_files/order.php'; +/** @var \Magento\Catalog\Model\Product $product */ + +/** @var OrderItem $orderItem */ +$orderItem = $objectManager->create(OrderItem::class); +$orderItem->setProductId($product->getId()) + ->setQtyOrdered(2) + ->setBasePrice($product->getPrice()) + ->setPrice($product->getPrice()) + ->setRowTotal($product->getPrice()) + ->setProductType('simple') + ->setName($product->getName()) + ->setFreeShipping('1'); + +/** @var Order $order */ +$order->setShippingDescription('Flat Rate - Fixed') + ->setShippingAmount(0) + ->setCouponCode('1234567890') + ->setDiscountDescription('1234567890') + ->addItem($orderItem); + +/** @var OrderRepositoryInterface $orderRepository */ +$orderRepository = $objectManager->create(OrderRepositoryInterface::class); +$orderRepository->save($order); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_free_shipping_by_coupon_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_free_shipping_by_coupon_rollback.php new file mode 100644 index 0000000000000..1fb4b4636ab29 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_free_shipping_by_coupon_rollback.php @@ -0,0 +1,8 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +require 'default_rollback.php'; From 1d91d51a37167eff1148664f9fdafe09a8eacdb8 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Tue, 26 Mar 2019 17:12:20 +0200 Subject: [PATCH 082/142] Fixed Ui typos --- .../Ui/view/base/web/js/lib/core/storage/local.js | 10 +++++----- .../base/web/js/lib/knockout/template/renderer.js | 2 +- .../Ui/view/base/web/js/lib/logger/logger-utils.js | 12 ++++++------ .../Ui/view/base/web/js/lib/validation/validator.js | 2 +- .../view/base/web/js/lib/view/utils/dom-observer.js | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/lib/core/storage/local.js b/app/code/Magento/Ui/view/base/web/js/lib/core/storage/local.js index 87b5b2f5fe8fe..adeb510ab3e40 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/core/storage/local.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/core/storage/local.js @@ -79,7 +79,7 @@ define([ /** * Extracts and parses data stored in localStorage by the - * key specified in 'root' varaible. + * key specified in 'root' variable. * * @returns {Object} */ @@ -114,8 +114,8 @@ define([ * * @param {String} path - Path to the property. * - * @example Retrieveing data. - * localStoarge => + * @example Retrieving data. + * localStorage => * 'appData' => ' * "one": {"two": "three"} * ' @@ -139,7 +139,7 @@ define([ * * @example Setting data. * storage.set('one.two', 'four'); - * => localStoarge => + * => localStorage => * 'appData' => ' * "one": {"two": "four"} * ' @@ -159,7 +159,7 @@ define([ * * @example Removing data. * storage.remove('one.two', 'four'); - * => localStoarge => + * => localStorage => * 'appData' => ' * "one": {} * ' diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js index 2e0c53373f807..2cfd961619249 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js @@ -519,7 +519,7 @@ define([ }, /** - * Custom 'render' attrobute handler function. Wraps child elements + * Custom 'render' attribute handler function. Wraps child elements * of a node with knockout's 'ko template:' comment tag. * * @param {HTMLElement} node - Element to be processed. diff --git a/app/code/Magento/Ui/view/base/web/js/lib/logger/logger-utils.js b/app/code/Magento/Ui/view/base/web/js/lib/logger/logger-utils.js index fe83f600132ed..bf7ae0cdc3e98 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/logger/logger-utils.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/logger/logger-utils.js @@ -42,14 +42,14 @@ define([], function () { * Method that creates object of messages * @param {String} requested - log message that showing that request for class is started * @param {String} loaded - log message that show when requested class is loaded - * @param {String} failded - log message that show when requested class is failed + * @param {String} failed - log message that show when requested class is failed * @returns {Object} */ - LogUtils.prototype.createMessages = function (requested, loaded, failded) { + LogUtils.prototype.createMessages = function (requested, loaded, failed) { return { requested: requested || '', loaded: loaded || '', - failed: failded || '' + failed: failed || '' }; }; @@ -57,14 +57,14 @@ define([], function () { * Method that creates object of log levels * @param {String} requested - log message that showing that request for class is started * @param {String} loaded - log message that show when requested class is loaded - * @param {String} failded - log message that show when requested class is failed + * @param {String} failed - log message that show when requested class is failed * @returns {Object} */ - LogUtils.prototype.createLevels = function (requested, loaded, failded) { + LogUtils.prototype.createLevels = function (requested, loaded, failed) { return { requested: requested || 'info', loaded: loaded || 'info', - failed: failded || 'warn' + failed: failed || 'warn' }; }; diff --git a/app/code/Magento/Ui/view/base/web/js/lib/validation/validator.js b/app/code/Magento/Ui/view/base/web/js/lib/validation/validator.js index 8ebbf88775b86..407984c7881a2 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/validation/validator.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/validation/validator.js @@ -64,7 +64,7 @@ define([ } /** - * Validates provied value by a specified set of rules. + * Validates provided value by a specified set of rules. * * @param {(String|Object)} rules - One or many validation rules. * @param {*} value - Value to be checked. diff --git a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js index 03012918f4a0d..f8e752fb77af2 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js @@ -141,7 +141,7 @@ define([ } /** - * Calls handlers assocoiated with an added node. + * Calls handlers associated with an added node. * Adds listeners for the node removal. * * @param {HTMLElement} node - Added node. @@ -163,7 +163,7 @@ define([ } /** - * Calls handlers assocoiated with a removed node. + * Calls handlers associated with a removed node. * * @param {HTMLElement} node - Removed node. */ From d073b0c6367c492637ce1aa8f007b5310a72825a Mon Sep 17 00:00:00 2001 From: Valerij Ivashchenko <likemusicdev@gmail.com> Date: Mon, 25 Mar 2019 22:53:25 +0300 Subject: [PATCH 083/142] Set minimum qty 1 after cast to int --- .../Magento/CatalogInventory/Model/StockStateProvider.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Model/StockStateProvider.php b/app/code/Magento/CatalogInventory/Model/StockStateProvider.php index 31fd5606a9849..e5b51ca37c6a2 100644 --- a/app/code/Magento/CatalogInventory/Model/StockStateProvider.php +++ b/app/code/Magento/CatalogInventory/Model/StockStateProvider.php @@ -1,4 +1,4 @@ -<?php +<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. @@ -119,14 +119,12 @@ public function checkQuoteItemQty(StockItemInterface $stockItem, $qty, $summaryQ $result->setItemIsQtyDecimal($stockItem->getIsQtyDecimal()); if (!$stockItem->getIsQtyDecimal()) { $result->setHasQtyOptionUpdate(true); - $qty = (int) $qty; + $qty = (int) $qty ?: 1; /** * Adding stock data to quote item */ $result->setItemQty($qty); - $qty = $this->getNumber($qty); - $origQty = (int) $origQty; - $result->setOrigQty($origQty); + $result->setOrigQty((int)$this->getNumber($origQty) ?: 1); } if ($stockItem->getMinSaleQty() && $qty < $stockItem->getMinSaleQty()) { From 6c7b1db8da645fe0e0d18e0239426142b41a7fab Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Tue, 26 Mar 2019 17:25:57 +0100 Subject: [PATCH 084/142] Fixed composer.json code style issue --- app/code/Magento/QuoteGraphQl/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/composer.json b/app/code/Magento/QuoteGraphQl/composer.json index b53cab6656217..22ca9cfdfae9a 100644 --- a/app/code/Magento/QuoteGraphQl/composer.json +++ b/app/code/Magento/QuoteGraphQl/composer.json @@ -11,7 +11,7 @@ "magento/module-store": "*", "magento/module-customer": "*", "magento/module-customer-graph-ql": "*", - "magento/module-sales" : "*" + "magento/module-sales": "*" }, "suggest": { "magento/module-graph-ql": "*" From b82503ae50f324ce9fb5add2b5e21159567b2412 Mon Sep 17 00:00:00 2001 From: Dmytro Cheshun <d.cheshun@atwix.com> Date: Tue, 26 Mar 2019 18:50:19 +0200 Subject: [PATCH 085/142] Fix encoding issue --- app/code/Magento/CatalogInventory/Model/StockStateProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogInventory/Model/StockStateProvider.php b/app/code/Magento/CatalogInventory/Model/StockStateProvider.php index e5b51ca37c6a2..6851b05aa56a6 100644 --- a/app/code/Magento/CatalogInventory/Model/StockStateProvider.php +++ b/app/code/Magento/CatalogInventory/Model/StockStateProvider.php @@ -1,4 +1,4 @@ -<?php +<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. From 120a8c06ab4b5d12a0e56ce93590870e1b752fe1 Mon Sep 17 00:00:00 2001 From: Akhilesh Singh Shrinet <alpha007_2008@yahoo.com> Date: Wed, 27 Mar 2019 01:16:28 +0530 Subject: [PATCH 086/142] Fixed WhiteSpace issue in product grid There are some whitespaces in between li tags, that's why product grid showing 3 products instead of 4. Mention in #20140 and #21244 --- .../luma/Magento_Catalog/web/css/source/module/_listings.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_listings.less b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_listings.less index e5915969c91b9..77fb53a2ab02a 100644 --- a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_listings.less +++ b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_listings.less @@ -34,12 +34,12 @@ .product { &-items { - font-size: 0; + .lib-inline-block-space-container(); &:extend(.abs-reset-list all); } &-item { - font-size: 1.4rem; + .lib-inline-block-space-item(); vertical-align: top; .products-grid & { From 01e7e08bf92afb696105fdfd3957c97fa316198b Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Wed, 27 Mar 2019 09:52:34 +0200 Subject: [PATCH 087/142] 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 | 5 +++++ .../testsuite/Magento/Sales/Block/Adminhtml/TotalsTest.php | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/Totals.php b/app/code/Magento/Sales/Block/Adminhtml/Totals.php index 3f08dc48d38d1..f26df0946168a 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Totals.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Totals.php @@ -7,6 +7,11 @@ use Magento\Sales\Model\Order; +/** + * Adminhtml sales totals block + * + * @package Magento\Sales\Block\Adminhtml + */ class Totals extends \Magento\Sales\Block\Order\Totals { /** 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 a77676e64a331..091b8e3f2b72c 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/TotalsTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/TotalsTest.php @@ -48,6 +48,10 @@ public function testShowShippingCoupon() $shippingTotal = $this->_block->getTotal('shipping'); $this->assertNotFalse($shippingTotal, 'Shipping method is absent on the total\'s block.'); - $this->assertContains('1234567890', $shippingTotal->getLabel(), 'Coupon code is absent in the shipping method label name.'); + $this->assertContains( + '1234567890', + $shippingTotal->getLabel(), + 'Coupon code is absent in the shipping method label name.' + ); } } From ed989a0c8843986ad29117915a5a74cb2523f166 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Wed, 27 Mar 2019 12:58:37 +0300 Subject: [PATCH 088/142] MAGETWO-70232: Import customizable options adds it to another product if same SKU is filled - Fixed unit test; --- app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php index 6b2f3aba12e7a..9cb6cda4d0a09 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php @@ -60,7 +60,7 @@ public function execute($entity, $arguments = []) } } if ($options) { - $this->processOptionsSaving($options, $entity->dataHasChangedFor('sku'), $entity->getSku()); + $this->processOptionsSaving($options, (bool)$entity->dataHasChangedFor('sku'), (string)$entity->getSku()); } return $entity; From c2fa0154abfa9a549b22280e4d1662de5e932c68 Mon Sep 17 00:00:00 2001 From: Jeroen <jeroen@reachdigital.nl> Date: Wed, 27 Mar 2019 12:24:10 +0100 Subject: [PATCH 089/142] Remove timestap from current date when saving product special price from date --- .../Observer/SetSpecialPriceStartDate.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Catalog/Observer/SetSpecialPriceStartDate.php b/app/code/Magento/Catalog/Observer/SetSpecialPriceStartDate.php index a597b8fddda9f..ed9f89efc6891 100644 --- a/app/code/Magento/Catalog/Observer/SetSpecialPriceStartDate.php +++ b/app/code/Magento/Catalog/Observer/SetSpecialPriceStartDate.php @@ -3,9 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Catalog\Observer; use Magento\Framework\Event\ObserverInterface; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; /** * Set value for Special Price start date @@ -13,21 +16,20 @@ class SetSpecialPriceStartDate implements ObserverInterface { /** - * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface + * @var TimezoneInterface */ private $localeDate; /** - * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate - * @codeCoverageIgnore + * @param TimezoneInterface $localeDate */ - public function __construct(\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate) + public function __construct(TimezoneInterface $localeDate) { $this->localeDate = $localeDate; } /** - * Set the current date to Special Price From attribute if it empty + * Set the current date to Special Price From attribute if it's empty. * * @param \Magento\Framework\Event\Observer $observer * @return $this @@ -36,8 +38,8 @@ public function execute(\Magento\Framework\Event\Observer $observer) { /** @var $product \Magento\Catalog\Model\Product */ $product = $observer->getEvent()->getProduct(); - if ($product->getSpecialPrice() && !$product->getSpecialFromDate()) { - $product->setData('special_from_date', $this->localeDate->date()); + if ($product->getSpecialPrice() && ! $product->getSpecialFromDate()) { + $product->setData('special_from_date', $this->localeDate->date()->setTime(0, 0)); } return $this; From 0d58dec4219792b6c5919ca9a445ae4cf5c06755 Mon Sep 17 00:00:00 2001 From: Veronika Kurochkina <veronika_kurochkina@epam.com> Date: Wed, 27 Mar 2019 14:49:06 +0300 Subject: [PATCH 090/142] MAGETWO-65232: Product name does not display special characters properly - Updated automated test script. --- .../Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml index 47fad10977b7c..76893f1c7deb3 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml @@ -52,7 +52,7 @@ <waitForPageLoad stepKey="waitForInvoicePageLoad"/> </actionGroup> - <actionGroup name="clearInvoicesGridFilers"> + <actionGroup name="clearInvoicesGridFilters"> <amOnPage url="{{AdminInvoicesPage.url}}" stepKey="goToInvoices"/> <waitForPageLoad stepKey="waitInvoicesGridToLoad"/> <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearFilters" /> From bfe315e65e2a907c6f67237e1068a04b1e6c164e Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Wed, 27 Mar 2019 14:11:00 -0500 Subject: [PATCH 091/142] MC-15439: Deferred loading / parsing of JS --- .../Controller/Result/JsFooterPlugin.php | 39 +++++++++++++++++++ app/code/Magento/Theme/etc/frontend/di.xml | 3 ++ 2 files changed, 42 insertions(+) create mode 100644 app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php diff --git a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php new file mode 100644 index 0000000000000..7bc02164e7a85 --- /dev/null +++ b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php @@ -0,0 +1,39 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Theme\Controller\Result; + +/** + * Plugin for putting messages to cookies + */ +class JsFooterPlugin +{ + /** + * Put all javascript to footer before sending the response + * + * @param \Magento\Framework\App\Response\Http $subject + * @return void + */ + 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); + $pattern = '#<script.*?</script>#is'; + $content = preg_replace_callback( + $pattern, + function ($matchPart) use (&$script) { + $script[] = $matchPart[0]; + return ''; + }, + $content + ); + $subject->setContent( + str_replace('</body', implode("\n", $script) . "\n</body", $content) + ); + } + } +} \ No newline at end of file diff --git a/app/code/Magento/Theme/etc/frontend/di.xml b/app/code/Magento/Theme/etc/frontend/di.xml index 7db2783cd8dfa..3837c6f717b54 100644 --- a/app/code/Magento/Theme/etc/frontend/di.xml +++ b/app/code/Magento/Theme/etc/frontend/di.xml @@ -26,4 +26,7 @@ <type name="Magento\Framework\Controller\ResultInterface"> <plugin name="result-messages" type="Magento\Theme\Controller\Result\MessagePlugin"/> </type> + <type name="Magento\Framework\App\Response\Http"> + <plugin name="result-js-footer" type="Magento\Theme\Controller\Result\JsFooterPlugin"/> + </type> </config> From a04154b10f2b62611722064085ede8cf03c50983 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Wed, 27 Mar 2019 22:49:58 +0200 Subject: [PATCH 092/142] 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 @@ +<?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="StorefrontCustomerAccountInformationSection"> + <element name="captchaField" type="input" selector="#captcha_user_edit"/> + <element name="captchaImg" type="block" selector=".captcha-img"/> + <element name="captchaReload" type="block" selector=".captcha-reload"/> + </section> +</sections> \ 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 @@ </after> <!-- Open Customer edit page --> - <amOnPage url="/customer/account/edit/" stepKey="goToEditPage"/> + <amOnPage url="{{StorefrontCustomerEditPage.url}}" stepKey="goToCustomerEditPage"/> <waitForPageLoad stepKey="waitForEditPage"/> <!-- Update email with incorrect password 3 times. --> - <click selector="{{StorefrontCustomerAccountInformationSection.changeEmail}}" stepKey="clickChangeEmailCheckbox1"/> - <fillField selector="{{StorefrontCustomerAccountInformationSection.currentPassword}}" userInput="incorrectPassword" stepKey="enterWrongPassword1"/> - <click selector="{{StorefrontCustomerAccountInformationSection.saveButton}}" stepKey="saveChange1"/> - <see userInput="The password doesn't match this account. Verify the password and try again." selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="verifyMessage1"/> + <actionGroup ref="StorefrontCustomerChangeEmailActionGroup" stepKey="changeEmailFirstAttempt"> + <argument name="email" value="$$customer.email$$" /> + <argument name="password" value="{{Colorado_US_Customer.password}}" /> + <argument name="message" value="The password doesn't match this account. Verify the password and try again." /> + <argument name="messageType" value="error" /> + </actionGroup> - <click selector="{{StorefrontCustomerAccountInformationSection.changeEmail}}" stepKey="clickChangeEmailCheckbox2"/> - <fillField selector="{{StorefrontCustomerAccountInformationSection.currentPassword}}" userInput="incorrectPassword" stepKey="enterWrongPassword2"/> - <click selector="{{StorefrontCustomerAccountInformationSection.saveButton}}" stepKey="saveChange2"/> - <see userInput="The password doesn't match this account. Verify the password and try again." selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="verifyMessage2"/> + <actionGroup ref="StorefrontCustomerChangeEmailActionGroup" stepKey="changeEmailSecondAttempt"> + <argument name="email" value="$$customer.email$$" /> + <argument name="password" value="{{Colorado_US_Customer.password}}" /> + <argument name="message" value="The password doesn't match this account. Verify the password and try again." /> + <argument name="messageType" value="error" /> + </actionGroup> - <click selector="{{StorefrontCustomerAccountInformationSection.changeEmail}}" stepKey="clickChangeEmailCheckbox3"/> - <fillField selector="{{StorefrontCustomerAccountInformationSection.currentPassword}}" userInput="incorrectPassword" stepKey="enterWrongPassword3"/> - <click selector="{{StorefrontCustomerAccountInformationSection.saveButton}}" stepKey="saveChange3"/> - <see userInput="The password doesn't match this account. Verify the password and try again." selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="verifyMessage3"/> + <actionGroup ref="StorefrontCustomerChangeEmailActionGroup" stepKey="changeEmailThirdAttempt"> + <argument name="email" value="$$customer.email$$" /> + <argument name="password" value="{{Colorado_US_Customer.password}}" /> + <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="{{StorefrontCustomerEditFormSection.captchaField}}" stepKey="seeCaptchaField"/> - <waitForElementVisible selector="{{StorefrontCustomerEditFormSection.captchaImg}}" stepKey="seeCaptchaImage"/> - <waitForElementVisible selector="{{StorefrontCustomerEditFormSection.captchaReload}}" stepKey="seeCaptchaReloadButton"/> + <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaField}}" stepKey="seeCaptchaField"/> + <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaImg}}" stepKey="seeCaptchaImage"/> + <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaReload}}" stepKey="seeCaptchaReloadButton"/> <reloadPage stepKey="refreshPage"/> - <waitForPageLoad stepKey="waitForPageLoad2"/> - <waitForElementVisible selector="{{StorefrontCustomerEditFormSection.captchaField}}" stepKey="seeCaptchaField2"/> - <waitForElementVisible selector="{{StorefrontCustomerEditFormSection.captchaImg}}" stepKey="seeCaptchaImage2"/> - <waitForElementVisible selector="{{StorefrontCustomerEditFormSection.captchaReload}}" stepKey="seeCaptchaReloadButton2"/> + <waitForPageLoad stepKey="waitForPageReloaded" /> + <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaField}}" stepKey="seeCaptchaFieldAfterPageReload"/> + <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaImg}}" stepKey="seeCaptchaImageAfterPageReload"/> + <waitForElementVisible selector="{{StorefrontCustomerAccountInformationSection.captchaReload}}" stepKey="seeCaptchaReloadButtonAfterPageReload"/> <!-- Try to submit form with incorrect captcha --> <click selector="{{StorefrontCustomerAccountInformationSection.changeEmail}}" stepKey="clickChangeEmailCheckbox4"/> <fillField selector="{{StorefrontCustomerAccountInformationSection.currentPassword}}" userInput="incorrectPassword" stepKey="enterWrongPassword4"/> - <fillField selector="{{StorefrontCustomerEditFormSection.captchaField}}" userInput="wrongCaptcha" stepKey="enterWrongCaptcha"/> + <fillField selector="{{StorefrontCustomerAccountInformationSection.captchaField}}" userInput="wrongCaptcha" stepKey="enterWrongCaptcha"/> <click selector="{{StorefrontCustomerAccountInformationSection.saveButton}}" stepKey="saveChange4"/> <see userInput="Incorrect CAPTCHA" selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="verifyMessage4"/> </test> 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 @@ +<?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="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" /> + </arguments> + <conditionalClick selector="{{StorefrontCustomerSidebarSection.sidebarTab('Account Information')}}" dependentSelector="{{StorefrontCustomerSidebarSection.sidebarTab('Account Information')}}" visible="true" stepKey="openAccountInfoTab" /> + <waitForPageLoad stepKey="waitForAccountInfoTabOpened" /> + <checkOption selector="{{StorefrontCustomerAccountInformationSection.changeEmail}}" stepKey="clickChangeEmailCheckbox" /> + <fillField selector="{{StorefrontCustomerAccountInformationSection.email}}" userInput="{{email}}" stepKey="fillEmail" /> + <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 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 @@ +<?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="StorefrontCustomerEditPage" url="/customer/account/edit/" area="storefront" module="Magento_Customer"> + <section name="StorefrontCustomerAccountInformationSection"/> + </page> +</pages> \ 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 @@ <section name="StorefrontCustomerAccountInformationSection"> <element name="firstName" type="input" selector="#firstname"/> <element name="lastName" type="input" selector="#lastname"/> - <element name="changeEmail" type="checkbox" selector="#change-email"/> - <element name="changePassword" type="checkbox" selector="#change-password"/> + <element name="changeEmail" type="checkbox" selector=".form-edit-account input[name='change_email']"/> + <element name="changePassword" type="checkbox" selector=".form-edit-account input[name='change_password']"/> <element name="testAddedAttributeFiled" type="input" selector="//input[contains(@id,'{{var}}')]" parameterized="true"/> <element name="saveButton" type="button" selector="#form-validate .action.save.primary" timeout="30"/> <element name="currentPassword" type="input" selector="#current-password"/> <element name="newPassword" type="input" selector="#password"/> <element name="confirmNewPassword" type="input" selector="#password-confirmation"/> <element name="confirmNewPasswordError" type="text" selector="#password-confirmation-error"/> - <element name="captchaField" type="input" selector="#captcha_user_edit"/> - <element name="captchaImg" type="block" selector=".captcha-img"/> - <element name="captchaReload" type="block" selector=".captcha-reload"/> + <element name="email" type="input" selector=".form-edit-account input[name='email']" /> </section> </sections> 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"> <section name="StorefrontCustomerAccountMainSection"> <element name="pageTitle" type="text" selector="#maincontent .column.main [data-ui-id='page-title-wrapper']" /> + <element name="messageByType" type="block" selector="#maincontent .message-{{messageType}}" parameterized="true" /> </section> </sections> 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 @@ <data name="attempts" xsi:type="number">3</data> <data name="captcha" xsi:type="string">111</data> <data name="configData" xsi:type="string">captcha_storefront_user_edit_failures_number, customer_max_login_failures_number</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Security\Test\Constraint\AssertCustomerIsLocked" /> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerIsLockedOnBackend" /> </variation> From 2d8404d59dafd97c4881dfb1529deb6ce3d8e0f6 Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Thu, 28 Mar 2019 12:04:25 +0200 Subject: [PATCH 093/142] 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 975872e4a5cd8b3b8642e22ff8260e5ddb830f74 Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Thu, 28 Mar 2019 15:09:29 +0200 Subject: [PATCH 094/142] 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 313f3952ffad8f19474995072c1b71ea1e566544 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 28 Mar 2019 16:08:31 +0200 Subject: [PATCH 095/142] 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 <enarc@atwix.com> Date: Thu, 28 Mar 2019 16:00:29 +0100 Subject: [PATCH 096/142] 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 @@ +<?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="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}}"/> + <click stepKey="clickForgotPasswordLink" selector="{{StorefrontCustomerSignInFormSection.forgotPasswordLink}}"/> + <see stepKey="seePageTitle" userInput="Forgot Your Password" selector="{{StorefrontForgotPasswordSection.pageTitle}}"/> + <!-- Enter email and submit the forgot password form --> + <fillField stepKey="fillEmailField" userInput="{{email}}" selector="{{StorefrontForgotPasswordSection.email}}"/> + <click stepKey="clickResetPassword" selector="{{StorefrontForgotPasswordSection.resetMyPasswordButton}}"/> + <waitForPageLoad stepKey="waitForPageLoaded" /> + <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/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 @@ <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/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 @@ <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> - <!-- Go to login page, and click on the forgot password link --> - <amOnPage stepKey="amOnSignInPage1" url="{{StorefrontCustomerSignInPage.url}}"/> - <click stepKey="clickForgotPasswordLink1" selector="{{StorefrontCustomerSignInFormSection.forgotPasswordLink}}"/> - <see stepKey="seePageTitle1" userInput="Forgot Your Password" selector="{{StorefrontForgotPasswordSection.pageTitle}}"/> - <!-- Enter email and submit the forgot password form --> - <fillField stepKey="enterEmail1" userInput="$$customer.email$$" selector="{{StorefrontForgotPasswordSection.email}}"/> - <click stepKey="clickResetPassword1" selector="{{StorefrontForgotPasswordSection.resetMyPasswordButton}}"/> - <seeInCurrentUrl stepKey="seeInSignInPage" url="account/login"/> - <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.successMessage}}" stepKey="waitForSuccessMessage" /> - <see stepKey="seeSuccessMessage" userInput="If there is an account associated with $$customer.email$$ you will receive an email with a link to reset your password." selector="{{StorefrontCustomerLoginMessagesSection.successMessage}}"/> - <!-- Repeat the procedure once again and ensure that on a second attempt customer sees an error --> - <amOnPage stepKey="amOnSignInPage2" url="{{StorefrontCustomerSignInPage.url}}"/> - <click stepKey="clickForgotPasswordLink2" selector="{{StorefrontCustomerSignInFormSection.forgotPasswordLink}}"/> - <see stepKey="seePageTitle2" userInput="Forgot Your Password" selector="{{StorefrontForgotPasswordSection.pageTitle}}"/> - <fillField stepKey="enterEmail2" userInput="$$customer.email$$" selector="{{StorefrontForgotPasswordSection.email}}"/> - <click stepKey="clickResetPassword2" selector="{{StorefrontForgotPasswordSection.resetMyPasswordButton}}"/> - <seeInCurrentUrl stepKey="seeInForgotPasswordPage" url="account/forgotpassword"/> - <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" stepKey="waitForFailMessage" /> - <see stepKey="seeFailMessage" userInput="We received too many requests for password resets. Please wait and try again later or contact hello@example.com." selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}"/> + + <actionGroup ref="StorefrontCustomerResetPasswordActionGroup" stepKey="resetPasswordFirstAttempt"> + <argument name="email" value="$$customer.email$$" /> + <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$$" /> + <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> </test> </tests> 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 097/142] 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 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 098/142] 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 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 099/142] 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 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 100/142] 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 101/142] 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 cb015a1dd94ed73623c620fd535e02131d3efb4c Mon Sep 17 00:00:00 2001 From: Ansari <ziyaurrahman@krishtechnolabs.com> Date: Sat, 30 Mar 2019 11:02:05 +0530 Subject: [PATCH 102/142] 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 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 103/142] 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 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 104/142] 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 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 105/142] 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 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 106/142] 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 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 107/142] 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 108/142] 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 ead2ab834ff52e43e797644a4297ea8b335a24ee Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Mon, 1 Apr 2019 23:18:30 +0300 Subject: [PATCH 109/142] 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 110/142] 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 111/142] 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 112/142] 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 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 113/142] 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 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 114/142] 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 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 115/142] 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 116/142] 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 117/142] 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 118/142] 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 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 119/142] 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 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 120/142] 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 121/142] 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 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 122/142] 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 123/142] 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 cae7e10ca75669cd7658113ec5ed6a9e4902f496 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Wed, 3 Apr 2019 11:21:16 +0300 Subject: [PATCH 124/142] 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 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 125/142] 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 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 126/142] 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 127/142] 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 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 128/142] 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 129/142] 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 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 130/142] 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 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 131/142] 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 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 132/142] 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 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 133/142] 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 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 134/142] 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 135/142] 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 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 136/142] 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 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 137/142] 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 138/142] 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 139/142] 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 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 140/142] 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 141/142] 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 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 142/142] 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>