From 65018524ccfcdff8b60a49d30b099c6cbffdc31e Mon Sep 17 00:00:00 2001 From: Dave Macaulay Date: Mon, 26 Nov 2018 16:02:34 -0600 Subject: [PATCH 01/50] MC-3812: Text/Banner - Stage Inline Editor becomes focused and editable after clicking Save button on Edit Form MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use correct API for setting content to ensure unexpected focusing doesn’t occur --- lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js index ede8dd2081fdf..2d7ea07cd823e 100644 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js @@ -350,7 +350,7 @@ define([ * @param {String} content */ setContent: function (content) { - this.get(this.getId()).execCommand('mceSetContent', false, content); + this.get(this.getId()).setContent(content); }, /** From 3ebea0e0ba2ea9bd7ab4e56224bea9086b563770 Mon Sep 17 00:00:00 2001 From: Dave Macaulay Date: Fri, 30 Nov 2018 15:45:41 -0600 Subject: [PATCH 02/50] MC-3812: Text/Banner - Stage Inline Editor becomes focused and editable after clicking Save button on Edit Form - Resolve issue with fixRangeSelection function --- lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js index 2d7ea07cd823e..ccfc82dcb0b75 100644 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js @@ -559,10 +559,12 @@ define([ var selection = editor.selection, dom = editor.dom, rng = dom.createRng(), + doc = editor.getDoc(), markerHtml, marker; - if (!selection.getContent().length) { + // Validate the range we're trying to fix is contained within the current editors document + if (!selection.getContent().length && jQuery.contains(doc, selection.getRng().startContainer)) { markerHtml = '\uFEFF'; selection.setContent(markerHtml); marker = dom.get('mce_marker'); From 3e44f8c891d4398db8f94ecf421b39bdb953eed7 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi Date: Wed, 5 Dec 2018 16:52:03 +0200 Subject: [PATCH 03/50] MAGETWO-96908: [2.3] Wrong attribute value in flat table --- .../Indexer/Product/Flat/FlatTableBuilder.php | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php index fbe0d4b550fa6..538d0e3a63488 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php @@ -346,12 +346,20 @@ protected function _updateTemporaryTableByStoreValues( } //Update not simple attributes (eg. dropdown) - if (isset($flatColumns[$attributeCode . $valueFieldSuffix])) { - $select = $this->_connection->select()->joinInner( - ['t' => $this->_productIndexerHelper->getTable('eav_attribute_option_value')], - 't.option_id = et.' . $attributeCode . ' AND t.store_id=' . $storeId, - [$attributeCode . $valueFieldSuffix => 't.value'] - ); + $columnName = $attributeCode . $valueFieldSuffix; + if (isset($flatColumns[$columnName])) { + $select = $this->_connection->select(); + $select->joinLeft( + ['t0' => $this->_productIndexerHelper->getTable('eav_attribute_option_value')], + 't0.option_id = et.' . $attributeCode . ' AND t0.store_id = 0', + [] + )->joinLeft( + ['ts' => $this->_productIndexerHelper->getTable('eav_attribute_option_value')], + 'ts.option_id = et.' . $attributeCode . ' AND ts.store_id = ' . $storeId, + [] + )->columns( + [$columnName => $this->_connection->getIfNullSql('ts.value', 't0.value')] + )->where($columnName . ' IS NOT NULL'); if (!empty($changedIds)) { $select->where($this->_connection->quoteInto('et.entity_id IN (?)', $changedIds)); } From e8f52d92cb37e88794352261454039661f047ab0 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi Date: Wed, 5 Dec 2018 16:57:44 +0200 Subject: [PATCH 04/50] MAGETWO-96908: [2.3] Wrong attribute value in flat table --- .../Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php index 538d0e3a63488..3b73d229d77a6 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php @@ -11,6 +11,7 @@ /** * Class FlatTableBuilder + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class FlatTableBuilder @@ -382,6 +383,8 @@ protected function _getTemporaryTableName($tableName) } /** + * Get metadata pool + * * @return \Magento\Framework\EntityManager\MetadataPool */ private function getMetadataPool() From 0e94d502b7717ab0abbc4e552007c96d3f02cbc0 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi Date: Wed, 5 Dec 2018 17:24:05 +0200 Subject: [PATCH 05/50] MAGETWO-96908: [2.3] Wrong attribute value in flat table --- .../Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php index 3b73d229d77a6..a3322b3231755 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php @@ -10,7 +10,7 @@ use Magento\Framework\EntityManager\MetadataPool; /** - * Class FlatTableBuilder + * Class for building flat index * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ From 669928e0c7b8c449ce22910732cf959ed9ac3e5b Mon Sep 17 00:00:00 2001 From: Myroslav Dobra Date: Thu, 6 Dec 2018 10:32:04 +0200 Subject: [PATCH 06/50] MAGETWO-95068: Checkout data (shipping address etc) not persistant after cart update --- ...StorefrontGuestCheckoutDataPersistTest.xml | 57 +++++++++++++++++++ .../view/frontend/web/js/customer-data.js | 3 + 2 files changed, 60 insertions(+) create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutDataPersistTest.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutDataPersistTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutDataPersistTest.xml new file mode 100644 index 0000000000000..626f095604fa2 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutDataPersistTest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + <description value="Checkout data should be persist after updating cart"/> + <severity value="CRITICAL"/> + <testCaseId value="MAGETWO-96979"/> + <group value="checkout"/> + </annotations> + <before> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="_defaultProduct" stepKey="createProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + </before> + <after> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + </after> + + <!-- Add simple product to cart --> + <actionGroup ref="AddSimpleProductToCart" stepKey="addProductToCart"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> + <!-- Navigate to checkout --> + <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart"/> + <!-- Fill shipping address --> + <actionGroup ref="GuestCheckoutFillingShippingSectionActionGroup" stepKey="guestCheckoutFillingShipping"> + <argument name="shippingMethod" value="Flat Rate"/> + </actionGroup> + <!-- Add simple product to cart --> + <actionGroup ref="AddSimpleProductToCart" stepKey="addProductToCart1"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> + <!-- Navigate to checkout --> + <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart1"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.email}}" userInput="{{CustomerEntityOne.email}}" stepKey="assertGuestEmail"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.firstName}}" userInput="{{CustomerEntityOne.firstname}}" stepKey="assertGuestFirstName"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.lastName}}" userInput="{{CustomerEntityOne.lastname}}" stepKey="assertGuestLastName"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.street}}" userInput="{{CustomerAddressSimple.street[0]}}" stepKey="assertGuestStreet"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.city}}" userInput="{{CustomerAddressSimple.city}}" stepKey="assertGuestCity"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.region}}" userInput="{{CustomerAddressSimple.state}}" stepKey="assertGuestRegion"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.postcode}}" userInput="{{CustomerAddressSimple.postcode}}" stepKey="assertGuestPostcode"/> + <seeInField selector="{{CheckoutShippingGuestInfoSection.telephone}}" userInput="{{CustomerAddressSimple.telephone}}" stepKey="assertGuestTelephone"/> + </test> +</tests> diff --git a/app/code/Magento/Customer/view/frontend/web/js/customer-data.js b/app/code/Magento/Customer/view/frontend/web/js/customer-data.js index 39e3f8d95ee3b..66d37cb84e9cb 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/customer-data.js +++ b/app/code/Magento/Customer/view/frontend/web/js/customer-data.js @@ -216,6 +216,9 @@ define([ $.cookieStorage.set(privateContentVersion, privateContent); } $.localStorage.set(privateContentVersion, privateContent); + _.each(dataProvider.getFromStorage(storage.keys()), function (sectionData, sectionName) { + buffer.notify(sectionName, sectionData); + }); this.reload([], false); isLoading = true; } else if (expiredSectionNames.length > 0) { From 2916b082a030746fa6943b00b6128e77d0d5b6f5 Mon Sep 17 00:00:00 2001 From: bshevchenko <1408sheva@gmail.com> Date: Mon, 10 Dec 2018 18:42:16 +0200 Subject: [PATCH 07/50] MAGETWO-96706: Cart Price Rule with related Banner for specific Customer Segment is persisted under long-term cookie --- .../Mftf/Section/AdminMainActionsSection.xml | 1 + .../Mftf/ActionGroup/CheckoutActionGroup.xml | 4 +- .../Section/StorefrontMiniCartSection.xml | 1 + .../Mftf/Section/StorefrontCMSPageSection.xml | 3 +- .../Cms/Test/Mftf/Section/TinyMCESection.xml | 1 + .../OpenEditCustomerFromAdminActionGroup.xml | 3 +- ...SignUpNewUserFromStorefrontActionGroup.xml | 2 +- .../Customer/Test/Mftf/Data/CustomerData.xml | 2 +- ...bscribedNewsletterDisplayedActionGroup.xml | 10 +- .../Page/StorefrontNewsletterManagePage.xml | 13 +++ .../StorFrontNewsletterManageSection.xml | 15 +++ .../AdminCartPriceRuleActionGroup.xml | 22 ++++ .../Data/SalesRuleAddressConditionsData.xml | 21 ++++ .../Test/Mftf/Data/SalesRuleCouponData.xml | 1 + .../Test/Mftf/Data/SalesRuleData.xml | 27 +++++ .../Mftf/Page/AdminCartPriceRuleEditPage.xml | 13 +++ .../AdminCartPriceRulesFormSection.xml | 6 + .../AdminCreateWidgetActionGroup.xml | 109 ++++++++++-------- .../Widget/Test/Mftf/Data/WidgetsData.xml | 15 ++- .../Test/Mftf/Page/AdminNewWidgetPage.xml | 4 +- .../Mftf/Section/AdminNewWidgetSection.xml | 5 +- 21 files changed, 212 insertions(+), 66 deletions(-) create mode 100644 app/code/Magento/Newsletter/Test/Mftf/Page/StorefrontNewsletterManagePage.xml create mode 100644 app/code/Magento/Newsletter/Test/Mftf/Section/StorFrontNewsletterManageSection.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleAddressConditionsData.xml create mode 100644 app/code/Magento/SalesRule/Test/Mftf/Page/AdminCartPriceRuleEditPage.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminMainActionsSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminMainActionsSection.xml index bc576559e7a13..c6d37291e625f 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminMainActionsSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminMainActionsSection.xml @@ -10,6 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminMainActionsSection"> <element name="save" type="button" selector="#save" timeout="30"/> + <element name="saveAndContinue" type="button" selector="#save_and_continue_edit" timeout="30"/> <element name="delete" type="button" selector="#delete" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml index 18bf70a613b50..e392e8e805e4a 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutActionGroup.xml @@ -91,8 +91,8 @@ <!-- Logged in user checkout filling shipping section --> <actionGroup name="LoggedInUserCheckoutFillingShippingSectionActionGroup"> <arguments> - <argument name="customerVar"/> - <argument name="customerAddressVar"/> + <argument name="customerVar" defaultValue="CustomerEntityOne"/> + <argument name="customerAddressVar" defaultValue="CustomerAddressSimple"/> </arguments> <fillField selector="{{CheckoutShippingSection.firstName}}" userInput="{{customerVar.firstname}}" stepKey="enterFirstName"/> <fillField selector="{{CheckoutShippingSection.lastName}}" userInput="{{customerVar.lastname}}" stepKey="enterLastName"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml index 3f717943fe8f0..a894f2fbb1af9 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml @@ -29,5 +29,6 @@ <element name="itemDiscount" type="text" selector="//tr[@class='totals']//td[@class='amount']/span"/> <element name="subtotal" type="text" selector="//tr[@class='totals sub']//td[@class='amount']/span"/> <element name="emptyCart" type="text" selector=".counter.qty.empty"/> + <element name="minicartContent" type="block" selector="#minicart-content-wrapper"/> </section> </sections> diff --git a/app/code/Magento/Cms/Test/Mftf/Section/StorefrontCMSPageSection.xml b/app/code/Magento/Cms/Test/Mftf/Section/StorefrontCMSPageSection.xml index 7a358c61263d6..b0262c18f1002 100644 --- a/app/code/Magento/Cms/Test/Mftf/Section/StorefrontCMSPageSection.xml +++ b/app/code/Magento/Cms/Test/Mftf/Section/StorefrontCMSPageSection.xml @@ -10,9 +10,10 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontCMSPageSection"> <element name="mediaDescription" type="text" selector=".column.main>p>img"/> - <element name="imageSource" type="text" selector="//img[contains(@src,'{{var1}}')]" parameterized="true"/> + <element name="imageSource" type="text" selector="//img[contains(@src,'{{imageName}}')]" parameterized="true"/> <element name="mainTitle" type="text" selector="#maincontent .page-title"/> <element name="mainContent" type="text" selector="#maincontent"/> <element name="footerTop" type="text" selector="footer.page-footer"/> + <element name="bannerImage" type="block" selector=".banner-items img"/> </section> </sections> diff --git a/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml b/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml index c7ea85e441bb9..89431a0c7ce4d 100644 --- a/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml +++ b/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml @@ -57,6 +57,7 @@ <element name="WysiwygArrow" type="button" selector="#d3lzaXd5Zw-- > .jstree-icon" /> <element name="checkIfWysiwygArrowExpand" type="button" selector="//li[@id='d3lzaXd5Zw--' and contains(@class,'jstree-closed')]" /> <element name="confirmDelete" type="button" selector=".action-primary.action-accept" /> + <element name="imageBlockByName" type="block" selector="//div[@data-row='file'][contains(., '{{imageName}}')]" parameterized="true"/> </section> <section name="VariableSection"> <element name="InsertWidget" type="button" selector="#insert_variable"/> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenEditCustomerFromAdminActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenEditCustomerFromAdminActionGroup.xml index 5b3a7a70aa2e6..14014505d6d24 100755 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenEditCustomerFromAdminActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenEditCustomerFromAdminActionGroup.xml @@ -22,10 +22,9 @@ </actionGroup> <actionGroup name="DeleteCustomerFromAdminActionGroup"> <arguments> - <argument name="customer"/> + <argument name="customer" defaultValue="CustomerEntityOne"/> </arguments> <amOnPage url="{{AdminCustomerPage.url}}" stepKey="navigateToCustomers"/> - <waitForPageLoad stepKey="waitForPageLoad1" /> <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clickOnButtonToRemoveFiltersIfPresent"/> <fillField selector="{{AdminDataGridHeaderSection.search}}" userInput="{{customer.email}}" stepKey="fillSearch"/> <click selector="{{AdminDataGridHeaderSection.submitSearch}}" stepKey="clickSubmit"/> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml index 79cc00d4474b1..aaca749e0e926 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml @@ -9,7 +9,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="SignUpNewUserFromStorefrontActionGroup"> <arguments> - <argument name="Customer"/> + <argument name="Customer" defaultValue="CustomerEntityOne"/> </arguments> <amOnPage stepKey="amOnStorefrontPage" url="/"/> <waitForPageLoad stepKey="waitForStorefrontPage"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml index 6f5ade53e6790..96bf654e63811 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml @@ -33,7 +33,7 @@ <!--requiredEntity type="extension_attribute">ExtensionAttributeSimple</requiredEntity--> </entity> <entity name="Simple_US_Customer" type="customer"> - <data key="group_id">0</data> + <data key="group_id">1</data> <data key="default_billing">true</data> <data key="default_shipping">true</data> <data key="email" unique="prefix">John.Doe@example.com</data> diff --git a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/VerifySubscribedNewsletterDisplayedActionGroup.xml b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/VerifySubscribedNewsletterDisplayedActionGroup.xml index 92d17e9d71e2f..de63fd34c62b4 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/VerifySubscribedNewsletterDisplayedActionGroup.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/VerifySubscribedNewsletterDisplayedActionGroup.xml @@ -6,13 +6,10 @@ */ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <!--Create an Account. Check Sign Up for Newsletter checkbox --> <actionGroup name="StorefrontCreateNewAccountNewsletterChecked" extends="SignUpNewUserFromStorefrontActionGroup"> - <arguments> - <argument name="Customer"/> - </arguments> <click selector="{{StorefrontCustomerCreateFormSection.signUpForNewsletter}}" stepKey="selectSignUpForNewsletterCheckbox" after="fillLastName"/> <see stepKey="seeDescriptionNewsletter" userInput='You are subscribed to "General Subscription".' selector="{{CustomerMyAccountPage.DescriptionNewsletter}}" /> </actionGroup> @@ -28,4 +25,9 @@ <see stepKey="seeThankYouMessage" userInput="Thank you for registering with NewStore."/> </actionGroup> + <!--Check Subscribed Newsletter via StoreFront--> + <actionGroup name="checkSubscribedNewsletterActionGroup"> + <amOnPage url="{{StorefrontNewsletterManagePage.url}}" stepKey="goToNewsletterManage"/> + <seeElement selector="{{StorefrontNewsletterManageSection.subscriptionChecked}}" stepKey="checkSubscribedNewsletter"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Page/StorefrontNewsletterManagePage.xml b/app/code/Magento/Newsletter/Test/Mftf/Page/StorefrontNewsletterManagePage.xml new file mode 100644 index 0000000000000..81fd3eb7c391c --- /dev/null +++ b/app/code/Magento/Newsletter/Test/Mftf/Page/StorefrontNewsletterManagePage.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="StorefrontNewsletterManagePage" url="newsletter/manage/" area="storefront" module="Magento_Newsletter"> + <section name="StorefrontNewsletterManageSection"/> + </page> +</pages> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Section/StorFrontNewsletterManageSection.xml b/app/code/Magento/Newsletter/Test/Mftf/Section/StorFrontNewsletterManageSection.xml new file mode 100644 index 0000000000000..4685e2b9a1ec1 --- /dev/null +++ b/app/code/Magento/Newsletter/Test/Mftf/Section/StorFrontNewsletterManageSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontNewsletterManageSection"> + <element name="subscriptionCheckbox" type="checkbox" selector="input#subscription" /> + <element name="subscriptionChecked" type="checkbox" selector="input#subscription[checked='checked']" /> + </section> +</sections> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCartPriceRuleActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCartPriceRuleActionGroup.xml index a794c67e736fc..541f745a6c941 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCartPriceRuleActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCartPriceRuleActionGroup.xml @@ -16,4 +16,26 @@ <!-- This actionGroup was created to be merged from B2B. Retailer Customer Group --> <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="Retailer" stepKey="selectRetailerCustomerGroup"/> </actionGroup> + + <!--Set Subtotal condition for Customer Segment--> + <actionGroup name="setCartAttributeConditionForCartPriceRuleActionGroup"> + <arguments> + <argument name="attributeName" type="string"/> + <argument name="operatorType" defaultValue="is" type="string"/> + <argument name="value" defaultValue="100" type="string"/> + </arguments> + <scrollTo selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" stepKey="scrollToActionTab"/> + <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeaderOpen}}" + visible="false" stepKey="openActionTab"/> + <click selector="{{AdminCartPriceRulesFormSection.conditions}}" stepKey="applyRuleForConditions"/> + <waitForPageLoad stepKey="waitForDropDownOpened"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.childAttribute}}" userInput="{{attributeName}}" stepKey="selectAttribute"/> + <waitForPageLoad stepKey="waitForOperatorOpened"/> + <click selector="{{AdminCartPriceRulesFormSection.condition('is')}}" stepKey="clickToChooseOption"/> + <selectOption userInput="{{operatorType}}" selector="{{AdminCartPriceRulesFormSection.conditionsOperator}}" stepKey="setOperatorType"/> + <click selector="{{AdminCartPriceRulesFormSection.condition('...')}}" stepKey="clickToChooseOption1"/> + <fillField userInput="{{value}}" selector="{{AdminCartPriceRulesFormSection.conditionsValue}}" stepKey="fillActionValue"/> + <click selector="{{AdminCartPriceRulesFormSection.saveAndContinue}}" stepKey="clickSaveButton"/> + <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleAddressConditionsData.xml b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleAddressConditionsData.xml new file mode 100644 index 0000000000000..5e9247825b29a --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleAddressConditionsData.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="SalesRuleAddressConditions" type="SalesRuleConditionAttribute"> + <data key="subtotal">Magento\SalesRule\Model\Rule\Condition\Address|base_subtotal</data> + <data key="totalItemsQty">Magento\SalesRule\Model\Rule\Condition\Address|total_qty</data> + <data key="totalWeight">Magento\SalesRule\Model\Rule\Condition\Address|weight</data> + <data key="shippingMethod">Magento\SalesRule\Model\Rule\Condition\Address|shipping_method</data> + <data key="shippingPostCode">Magento\SalesRule\Model\Rule\Condition\Address|postcode</data> + <data key="shippingRegion">Magento\SalesRule\Model\Rule\Condition\Address|region</data> + <data key="shippingState">Magento\SalesRule\Model\Rule\Condition\Address|region_id</data> + <data key="ShippingCountry">Magento\SalesRule\Model\Rule\Condition\Address|country_id</data> + </entity> +</entities> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleCouponData.xml b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleCouponData.xml index 10b198b53f389..3dd87d94d0148 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleCouponData.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleCouponData.xml @@ -11,5 +11,6 @@ <var key="rule_id" entityKey="rule_id" entityType="SalesRule"/> <data key="code" unique="suffix">Code</data> <data key="is_primary">1</data> + <data key="times_used">0</data> </entity> </entities> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml index 6f9d267fd1fd1..d032b2c1b2e4f 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml @@ -117,4 +117,31 @@ <data key="uses_per_coupon">2</data> <data key="simple_free_shipping">1</data> </entity> + + <entity name="SalesRuleSpecificCouponWithPercentDiscount" type="SalesRule"> + <data key="name" unique="suffix">SimpleSalesRule</data> + <data key="description">Sales Rule Description</data> + <array key="website_ids"> + <item>1</item> + </array> + <array key="customer_group_ids"> + <item>1</item> + </array> + <data key="uses_per_customer">10</data> + <data key="is_active">true</data> + <data key="stop_rules_processing">false</data> + <data key="is_advanced">true</data> + <data key="sort_order">1</data> + <data key="simple_action">by_percent</data> + <data key="discount_amount">10</data> + <data key="discount_qty">10</data> + <data key="discount_step">0</data> + <data key="apply_to_shipping">false</data> + <data key="times_used">0</data> + <data key="is_rss">false</data> + <data key="coupon_type">SPECIFIC_COUPON</data> + <data key="use_auto_generation">false</data> + <data key="uses_per_coupon">10</data> + <data key="simple_free_shipping">1</data> + </entity> </entities> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Page/AdminCartPriceRuleEditPage.xml b/app/code/Magento/SalesRule/Test/Mftf/Page/AdminCartPriceRuleEditPage.xml new file mode 100644 index 0000000000000..faed9d42bcdec --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Mftf/Page/AdminCartPriceRuleEditPage.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="AdminCartPriceRuleEditPage" area="admin" url="sales_rule/promo_quote/edit/id/{{salesRuleId}}" module="Magento_SalesRule" parameterized="true"> + <section name="AdminCartPriceRulesFormSection"/> + </page> +</pages> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml index 9ffb703fdf0f6..e36183b5b45a1 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesFormSection.xml @@ -27,6 +27,12 @@ <element name="userPerCustomer" type="input" selector="//input[@name='uses_per_customer']"/> <element name="priority" type="input" selector="//*[@name='sort_order']"/> + <!-- Conditions sub-form --> + <element name="conditionsHeader" type="button" selector="div[data-index='conditions']" timeout="30"/> + <element name="conditionsHeaderOpen" type="button" selector="div[data-index='conditions'] div[data-state-collapsible='open']" timeout="30"/> + <element name="conditionsValue" type="input" selector=".rule-param-edit input"/> + <element name="conditionsOperator" type="select" selector=".rule-param-edit select"/> + <!-- Actions sub-form --> <element name="actionsTab" type="text" selector="//div[@data-index='actions']//span[contains(.,'Actions')][1]"/> <element name="actionsHeader" type="button" selector="div[data-index='actions']" timeout="30"/> diff --git a/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml b/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml index 7955f4ec29e55..642ad6a268201 100644 --- a/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml +++ b/app/code/Magento/Widget/Test/Mftf/ActionGroup/AdminCreateWidgetActionGroup.xml @@ -7,55 +7,62 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminCreateProductsListWidgetActionGroup"> - <arguments> - <argument name="widget"/> - </arguments> - <amOnPage url="{{AdminDashboardPage.url}}" stepKey="amOnAdminDashboard"/> - <click selector="{{AdminMenuSection.content}}" stepKey="clickContent"/> - <waitForLoadingMaskToDisappear stepKey="waitForWidgets" /> - <click selector="{{AdminMenuSection.widgets}}" stepKey="clickWidgets"/> - <waitForPageLoad stepKey="waitForWidgetsLoad"/> - <click selector="{{AdminGridMainControls.add}}" stepKey="addNewWidget"/> - <selectOption selector="{{AdminNewWidgetSection.widgetType}}" userInput="{{widget.type}}" stepKey="setWidgetType"/> - <selectOption selector="{{AdminNewWidgetSection.widgetDesignTheme}}" userInput="{{widget.design_theme}}" stepKey="setWidgetDesignTheme"/> - <click selector="{{AdminNewWidgetSection.continue}}" stepKey="clickContinue"/> - <fillField selector="{{AdminNewWidgetSection.widgetTitle}}" userInput="{{widget.name}}" stepKey="fillTitle"/> - <selectOption selector="{{AdminNewWidgetSection.widgetStoreIds}}" userInput="{{widget.store_ids[0]}}" stepKey="setWidgetStoreIds"/> - <click selector="{{AdminNewWidgetSection.addLayoutUpdate}}" stepKey="clickAddLayoutUpdate"/> - <selectOption selector="{{AdminNewWidgetSection.selectDisplayOn}}" userInput="{{widget.display_on}}" stepKey="setDisplayOn"/> - <waitForAjaxLoad stepKey="waitForLoad"/> - <selectOption selector="{{AdminNewWidgetSection.selectContainer}}" userInput="{{widget.container}}" stepKey="setContainer"/> - <waitForAjaxLoad stepKey="waitForPageLoad"/> - <scrollToTopOfPage stepKey="scrollToTopOfPage"/> - <click selector="{{AdminNewWidgetSection.widgetOptions}}" stepKey="clickWidgetOptions"/> - <click selector="{{AdminNewWidgetSection.addNewCondition}}" stepKey="clickAddNewCondition"/> - <selectOption selector="{{AdminNewWidgetSection.selectCondition}}" userInput="{{widget.condition}}" stepKey="selectCondition"/> - <waitForElement selector="{{AdminNewWidgetSection.ruleParameter}}" stepKey="waitRuleParameter"/> - <click selector="{{AdminNewWidgetSection.ruleParameter}}" stepKey="clickRuleParameter"/> - <click selector="{{AdminNewWidgetSection.openChooser}}" stepKey="clickChooser"/> - <waitForAjaxLoad stepKey="waitForAjaxLoad"/> - <click selector="{{AdminNewWidgetSection.selectAll}}" stepKey="clickSelectAll"/> - <click selector="{{AdminNewWidgetSection.applyParameter}}" stepKey="clickApplyRuleParameter"/> - <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveWidget"/> - <waitForPageLoad stepKey="waitForSaveLoad"/> - <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been saved" stepKey="seeSuccess"/> - </actionGroup> - <actionGroup name="AdminDeleteWidgetActionGroup"> - <arguments> - <argument name="widget"/> - </arguments> - <amOnPage url="{{AdminWidgetsPage.url}}" stepKey="amOnAdmin"/> - <waitForPageLoad stepKey="waitWidgetsLoad"/> - <fillField selector="{{AdminWidgetsSection.widgetTitleSearch}}" userInput="{{widget.name}}" stepKey="fillTitle"/> - <click selector="{{AdminWidgetsSection.searchButton}}" stepKey="clickContinue"/> - <click selector="{{AdminWidgetsSection.searchResult}}" stepKey="clickSearchResult"/> - <waitForPageLoad stepKey="waitForResultLoad"/> - <click selector="{{AdminMainActionsSection.delete}}" stepKey="clickDelete"/> - <waitForAjaxLoad stepKey="waitForAjaxLoad"/> - <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="confirmDelete"/> - <waitForPageLoad stepKey="waitForDeleteLoad"/> - <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been deleted" stepKey="seeSuccess"/> - </actionGroup> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateWidgetActionGroup"> + <arguments> + <argument name="widget"/> + </arguments> + <amOnPage url="{{AdminNewWidgetPage.url}}" stepKey="amOnAdminNewWidgetPage"/> + <selectOption selector="{{AdminNewWidgetSection.widgetType}}" userInput="{{widget.type}}" stepKey="setWidgetType"/> + <selectOption selector="{{AdminNewWidgetSection.widgetDesignTheme}}" userInput="{{widget.design_theme}}" stepKey="setWidgetDesignTheme"/> + <click selector="{{AdminNewWidgetSection.continue}}" stepKey="clickContinue"/> + <fillField selector="{{AdminNewWidgetSection.widgetTitle}}" userInput="{{widget.name}}" stepKey="fillTitle"/> + <selectOption selector="{{AdminNewWidgetSection.widgetStoreIds}}" userInput="{{widget.store_ids[0]}}" stepKey="setWidgetStoreIds"/> + <click selector="{{AdminNewWidgetSection.addLayoutUpdate}}" stepKey="clickAddLayoutUpdate"/> + <selectOption selector="{{AdminNewWidgetSection.selectDisplayOn}}" userInput="{{widget.display_on}}" stepKey="setDisplayOn"/> + <waitForAjaxLoad stepKey="waitForLoad"/> + <selectOption selector="{{AdminNewWidgetSection.selectContainer}}" userInput="{{widget.container}}" stepKey="setContainer"/> + <waitForAjaxLoad stepKey="waitForPageLoad"/> + <scrollToTopOfPage stepKey="scrollToTopOfPage"/> + <click selector="{{AdminNewWidgetSection.widgetOptions}}" stepKey="clickWidgetOptions"/> + </actionGroup> + + <!--Create Product List Widget--> + <actionGroup name="AdminCreateProductsListWidgetActionGroup" extends="AdminCreateWidgetActionGroup"> + <click selector="{{AdminNewWidgetSection.addNewCondition}}" stepKey="clickAddNewCondition"/> + <selectOption selector="{{AdminNewWidgetSection.selectCondition}}" userInput="{{widget.condition}}" stepKey="selectCondition"/> + <waitForElement selector="{{AdminNewWidgetSection.ruleParameter}}" stepKey="waitRuleParameter"/> + <click selector="{{AdminNewWidgetSection.ruleParameter}}" stepKey="clickRuleParameter"/> + <click selector="{{AdminNewWidgetSection.openChooser}}" stepKey="clickChooser"/> + <waitForAjaxLoad stepKey="waitForAjaxLoad"/> + <click selector="{{AdminNewWidgetSection.selectAll}}" stepKey="clickSelectAll"/> + <click selector="{{AdminNewWidgetSection.applyParameter}}" stepKey="clickApplyRuleParameter"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveWidget"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been saved" stepKey="seeSuccess"/> + </actionGroup> + + <!--Create Dynamic Block Rotate Widget--> + <actionGroup name="AdminCreateDynamicBlocksRotatorWidgetActionGroup" extends="AdminCreateWidgetActionGroup"> + <selectOption selector="{{AdminNewWidgetSection.displayMode}}" userInput="{{widget.display_mode}}" stepKey="selectDisplayMode"/> + <selectOption selector="{{AdminNewWidgetSection.restrictTypes}}" userInput="{{widget.restrict_type}}" stepKey="selectRestrictType"/> + <click selector="{{AdminNewWidgetSection.saveAndContinue}}" stepKey="clickSaveWidget"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been saved" stepKey="seeSuccess"/> + </actionGroup> + + <actionGroup name="AdminDeleteWidgetActionGroup"> + <arguments> + <argument name="widget"/> + </arguments> + <amOnPage url="{{AdminWidgetsPage.url}}" stepKey="amOnAdmin"/> + <waitForPageLoad stepKey="waitWidgetsLoad"/> + <fillField selector="{{AdminWidgetsSection.widgetTitleSearch}}" userInput="{{widget.name}}" stepKey="fillTitle"/> + <click selector="{{AdminWidgetsSection.searchButton}}" stepKey="clickContinue"/> + <click selector="{{AdminWidgetsSection.searchResult}}" stepKey="clickSearchResult"/> + <waitForPageLoad stepKey="waitForResultLoad"/> + <click selector="{{AdminMainActionsSection.delete}}" stepKey="clickDelete"/> + <waitForAjaxLoad stepKey="waitForAjaxLoad"/> + <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="confirmDelete"/> + <waitForPageLoad stepKey="waitForDeleteLoad"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="The widget instance has been deleted" stepKey="seeSuccess"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml b/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml index 26864c60b6494..27222298408de 100644 --- a/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml +++ b/app/code/Magento/Widget/Test/Mftf/Data/WidgetsData.xml @@ -7,7 +7,7 @@ --> <entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> <entity name="ProductsListWidget" type="widget"> <data key="type">Catalog Products List</data> <data key="design_theme">Magento Luma</data> @@ -19,4 +19,17 @@ <data key="display_on">All Pages</data> <data key="container">Main Content Area</data> </entity> + <entity name="DynamicBlocksRotatorWidget" type="widget"> + <data key="type">Dynamic Blocks Rotator</data> + <data key="design_theme">Magento Luma</data> + <data key="name" unique="suffix">TestBannerWidget</data> + <array key="store_ids"> + <item>All Store Views</item> + </array> + <data key="condition">SKU</data> + <data key="display_on">All Pages</data> + <data key="container">Main Content Area</data> + <data key="display_mode">Cart Price Rule Related</data> + <data key="restrict_type">Header</data> + </entity> </entities> diff --git a/app/code/Magento/Widget/Test/Mftf/Page/AdminNewWidgetPage.xml b/app/code/Magento/Widget/Test/Mftf/Page/AdminNewWidgetPage.xml index 8eb0a5f65318e..d495a36f68d0a 100644 --- a/app/code/Magento/Widget/Test/Mftf/Page/AdminNewWidgetPage.xml +++ b/app/code/Magento/Widget/Test/Mftf/Page/AdminNewWidgetPage.xml @@ -7,8 +7,8 @@ --> <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd"> - <page name="AdminNewWidgetPage" url="admin/admin/widget_instance/new/" area="admin" module="Magento_Widget"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="AdminNewWidgetPage" url="admin/widget_instance/new/" area="admin" module="Magento_Widget"> <section name="AdminNewWidgetSection"/> </page> </pages> diff --git a/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml b/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml index 38b4df335ea83..aea74b573ce11 100644 --- a/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml +++ b/app/code/Magento/Widget/Test/Mftf/Section/AdminNewWidgetSection.xml @@ -7,7 +7,7 @@ --> <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminNewWidgetSection"> <element name="widgetType" type="select" selector="#code"/> <element name="widgetDesignTheme" type="select" selector="#theme_id"/> @@ -25,5 +25,8 @@ <element name="applyParameter" type="button" selector=".rule-param-apply"/> <element name="openChooser" type="button" selector=".rule-chooser-trigger"/> <element name="selectAll" type="checkbox" selector=".admin__control-checkbox"/> + <element name="displayMode" type="select" selector="select[id*='display_mode']"/> + <element name="restrictTypes" type="select" selector="select[id*='types']"/> + <element name="saveAndContinue" type="button" selector="#save_and_edit_button" timeout="30"/> </section> </sections> From 7ac90f4378ed6c328f39ce5e3d0a8954b4ac6277 Mon Sep 17 00:00:00 2001 From: Mariana Lashch <mlashch@magento.com> Date: Thu, 13 Dec 2018 13:32:12 +0200 Subject: [PATCH 08/50] MAGETWO-96379: Cart Price Rule grid count and pagination is wrong - create mftf test --- .../AdminGetWebsiteIdActionGroup.xml | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 app/code/Magento/Store/Test/Mftf/ActionGroup/AdminGetWebsiteIdActionGroup.xml diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminGetWebsiteIdActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminGetWebsiteIdActionGroup.xml new file mode 100644 index 0000000000000..d7f5a6bcdb853 --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminGetWebsiteIdActionGroup.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Admin creates new custom website --> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!--Get Website id--> + <actionGroup name="AdminGetWebsiteIdActionGroup"> + <arguments> + <argument name="website"/> + </arguments> + <amOnPage url="{{AdminSystemStorePage.url}}" stepKey="amOnTheStorePage"/> + <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters"/> + <fillField selector="{{AdminStoresGridSection.websiteFilterTextField}}" userInput="{{website.name}}" stepKey="fillSearchWebsiteField"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickApplyFilters" /> + <see selector="{{AdminStoresGridSection.websiteNameInFirstRow}}" userInput="{{website.name}}" stepKey="verifyThatCorrectWebsiteFound"/> + <click selector="{{AdminStoresGridSection.websiteNameInFirstRow}}" stepKey="clickEditExistingWebsite"/> + <grabFromCurrentUrl regex="~(\d+)/~" stepKey="grabFromCurrentUrl"/> + </actionGroup> +</actionGroups> \ No newline at end of file From 2ab53e88eefeae02dbef8c4a2776719074b666c2 Mon Sep 17 00:00:00 2001 From: Mariana Lashch <mlashch@magento.com> Date: Thu, 13 Dec 2018 13:53:53 +0200 Subject: [PATCH 09/50] MAGETWO-96379: Cart Price Rule grid count and pagination is wrong - add selectors --- .../Test/Mftf/Section/AdminCartPriceRulesSection.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml index a32c50d9d8617..814731688c814 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml @@ -15,5 +15,7 @@ <element name="nameColumns" type="text" selector="td[data-column='name']"/> <element name="rowContainingText" type="text" selector="//*[@id='promo_quote_grid_table']/tbody/tr[td//text()[contains(., '{{var1}}')]]" parameterized="true" timeout="30"/> <element name="rowByIndex" type="text" selector="tr[data-role='row']:nth-of-type({{var1}})" parameterized="true" timeout="30"/> - </section> + <element name="rulesRow" type="text" selector="//tr[@data-role='row']"/> + <element name="buttonNextInactive" type="button" selector="//button[@class='action-next disabled']"/> + </section> </sections> From 392802c7033bc3abd4e506c17e69d90907ea0451 Mon Sep 17 00:00:00 2001 From: Mariana Lashch <mlashch@magento.com> Date: Thu, 13 Dec 2018 14:57:41 +0200 Subject: [PATCH 10/50] MAGETWO-96379: Cart Price Rule grid count and pagination is wrong - add changes --- .../SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml index 814731688c814..55b4681580bb3 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml @@ -17,5 +17,5 @@ <element name="rowByIndex" type="text" selector="tr[data-role='row']:nth-of-type({{var1}})" parameterized="true" timeout="30"/> <element name="rulesRow" type="text" selector="//tr[@data-role='row']"/> <element name="buttonNextInactive" type="button" selector="//button[@class='action-next disabled']"/> - </section> + </section> </sections> From 46f47ce01f2a51747baa5e03becae4b560e3b3b2 Mon Sep 17 00:00:00 2001 From: Mariana Lashch <mlashch@magento.com> Date: Sun, 16 Dec 2018 20:08:56 +0200 Subject: [PATCH 11/50] MAGETWO-96379: Cart Price Rule grid count and pagination is wrong - complete mftf test --- .../AdminCreateCartPriceRuleActionGroup.xml | 11 +++++++++ .../Section/AdminCartPriceRulesSection.xml | 2 +- .../AdminGetWebsiteIdActionGroup.xml | 24 ------------------- 3 files changed, 12 insertions(+), 25 deletions(-) delete mode 100644 app/code/Magento/Store/Test/Mftf/ActionGroup/AdminGetWebsiteIdActionGroup.xml diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml index 6ee7b556beb7d..adcaa429be384 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml @@ -36,4 +36,15 @@ <click selector="{{AdminCartPriceRulesFormSection.delete}}" stepKey="clickDeleteButton"/> <click selector="{{AdminCartPriceRulesFormSection.modalAcceptButton}}" stepKey="confirmDelete"/> </actionGroup> + + <actionGroup name="CreateCartPriceRuleSecondWebsiteActionGroup"> + <arguments> + <argument name="ruleName"/> + </arguments> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> + <waitForPageLoad stepKey="waitForPriceList"/> + <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{ruleName.name}}" stepKey="fillRuleName"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="Second Website" stepKey="selectWebsites"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml index 55b4681580bb3..3d2682bf55713 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml @@ -16,6 +16,6 @@ <element name="rowContainingText" type="text" selector="//*[@id='promo_quote_grid_table']/tbody/tr[td//text()[contains(., '{{var1}}')]]" parameterized="true" timeout="30"/> <element name="rowByIndex" type="text" selector="tr[data-role='row']:nth-of-type({{var1}})" parameterized="true" timeout="30"/> <element name="rulesRow" type="text" selector="//tr[@data-role='row']"/> - <element name="buttonNextInactive" type="button" selector="//button[@class='action-next disabled']"/> + <element name="pageCurrent" type="text" selector="//label[@for='promo_quote_grid_page-current']"/> </section> </sections> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminGetWebsiteIdActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminGetWebsiteIdActionGroup.xml deleted file mode 100644 index d7f5a6bcdb853..0000000000000 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminGetWebsiteIdActionGroup.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<!-- Admin creates new custom website --> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <!--Get Website id--> - <actionGroup name="AdminGetWebsiteIdActionGroup"> - <arguments> - <argument name="website"/> - </arguments> - <amOnPage url="{{AdminSystemStorePage.url}}" stepKey="amOnTheStorePage"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters"/> - <fillField selector="{{AdminStoresGridSection.websiteFilterTextField}}" userInput="{{website.name}}" stepKey="fillSearchWebsiteField"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickApplyFilters" /> - <see selector="{{AdminStoresGridSection.websiteNameInFirstRow}}" userInput="{{website.name}}" stepKey="verifyThatCorrectWebsiteFound"/> - <click selector="{{AdminStoresGridSection.websiteNameInFirstRow}}" stepKey="clickEditExistingWebsite"/> - <grabFromCurrentUrl regex="~(\d+)/~" stepKey="grabFromCurrentUrl"/> - </actionGroup> -</actionGroups> \ No newline at end of file From 0e0f413b01d7c73dc6f4ffbfd7b490609273467b Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Tue, 18 Dec 2018 10:34:07 +0200 Subject: [PATCH 12/50] MAGETWO-97034: Import Products with Delete Entities --- .../Test/Mftf/Page/AdminImportIndexPage.xml | 15 ++++ .../Mftf/Section/AdminImportHeaderSection.xml | 14 ++++ .../Mftf/Section/AdminImportMainSection.xml | 18 +++++ ...inImportProductsWithDeleteEntitiesTest.xml | 76 +++++++++++++++++++ .../Section/AdminDataGridTableSection.xml | 1 + .../tests/_data/catalog_products.csv | 5 ++ 6 files changed, 129 insertions(+) create mode 100644 app/code/Magento/ImportExport/Test/Mftf/Page/AdminImportIndexPage.xml create mode 100644 app/code/Magento/ImportExport/Test/Mftf/Section/AdminImportHeaderSection.xml create mode 100644 app/code/Magento/ImportExport/Test/Mftf/Section/AdminImportMainSection.xml create mode 100644 app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml create mode 100644 dev/tests/acceptance/tests/_data/catalog_products.csv diff --git a/app/code/Magento/ImportExport/Test/Mftf/Page/AdminImportIndexPage.xml b/app/code/Magento/ImportExport/Test/Mftf/Page/AdminImportIndexPage.xml new file mode 100644 index 0000000000000..87807eb9b0e85 --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Mftf/Page/AdminImportIndexPage.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="AdminImportIndexPage" url="admin/import/" area="admin" module="Magento_ImportExport"> + <section name="AdminImportHeaderSection"/> + <section name="AdminImportMainSection"/> + </page> +</pages> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Section/AdminImportHeaderSection.xml b/app/code/Magento/ImportExport/Test/Mftf/Section/AdminImportHeaderSection.xml new file mode 100644 index 0000000000000..748580be09406 --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Mftf/Section/AdminImportHeaderSection.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="AdminImportHeaderSection"> + <element name="checkDataButton" type="button" selector="#upload_button" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Section/AdminImportMainSection.xml b/app/code/Magento/ImportExport/Test/Mftf/Section/AdminImportMainSection.xml new file mode 100644 index 0000000000000..365aca53b4dc0 --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Mftf/Section/AdminImportMainSection.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminImportMainSection"> + <element name="entityType" type="select" selector="#entity"/> + <element name="importBehavior" type="select" selector="#basic_behavior"/> + <element name="selectFileToImport" type="input" selector="#import_file"/> + <element name="importButton" type="button" selector="#import_validation_container button" timeout="30"/> + <element name="noticeMessage" type="text" selector="#import_validation_messages .message.message-notice.notice"/> + </section> +</sections> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml new file mode 100644 index 0000000000000..805c7141bfdff --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml @@ -0,0 +1,76 @@ +<?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="AdminImportProductsWithDeleteEntitiesTest"> + <annotations> + <description value="Verify Magento native import products with delete behavior."/> + <stories value="Verify Magento native import products with delete behavior."/> + <features value="Import/Export"/> + <title value="Verify Magento native import products with delete behavior."/> + <severity value="CRITICAL"/> + <testCaseId value="MAGETWO-30587"/> + <group value="importExport"/> + </annotations> + <before> + <!--Create Simple product--> + <createData entity="SimpleProduct2" stepKey="createSimpleProduct"> + <field key="name">Simple Product for Test</field> + <field key="sku">Simple Product for Test</field> + </createData> + <!--Create Virtual product--> + <createData entity="VirtualProduct" stepKey="createVirtualProduct"> + <field key="name">Virtual Product for Test</field> + <field key="sku">Virtual Product for Test</field> + </createData> + <!--Create Gift Card product--> + <createData entity="ApiGiftCard" stepKey="createApiGiftCard"> + <field key="name">Api Gift Card for Test</field> + <field key="sku">Api Gift Card for Test</field> + </createData> + <!-- Create Downloadable product --> + <createData entity="ApiDownloadableProduct" stepKey="createDownloadableProduct"> + <field key="name">Api Downloadable Product for Test</field> + <field key="sku">Api Downloadable Product for Test</field> + </createData> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductFilters"/> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + </after> + <amOnPage url="{{AdminImportIndexPage.url}}" stepKey="goToImportIndexPage"/> + <selectOption selector="{{AdminImportMainSection.entityType}}" userInput="Products" stepKey="selectProductsOption"/> + <waitForElementVisible selector="{{AdminImportMainSection.importBehavior}}" stepKey="waitForImportBehaviorElementVisible"/> + <selectOption selector="{{AdminImportMainSection.importBehavior}}" userInput="Delete" stepKey="selectDeleteOption"/> + <attachFile selector="{{AdminImportMainSection.selectFileToImport}}" userInput="catalog_products.csv" stepKey="attachFileForImport"/> + <click selector="{{AdminImportHeaderSection.checkDataButton}}" stepKey="clickCheckDataButton"/> + <waitForAjaxLoad stepKey="waitForFileToImportProcessed"/> + <click selector="{{AdminImportMainSection.importButton}}" stepKey="clickImportButton"/> + <waitForAjaxLoad stepKey="waitForFileToImportProcessed1"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="Import successfully done" stepKey="assertSuccessMessage"/> + <see selector="{{AdminImportMainSection.noticeMessage}}" userInput="Created: 0, Updated: 0, Deleted: 4" stepKey="assertNoticeMessage"/> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchSimpleProductOnBackend"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <see selector="{{AdminDataGridTableSection.dataGridNoData}}" userInput="We couldn't find any records." stepKey="assertDataGridNoDataMessage"/> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchVirtualProductOnBackend"> + <argument name="product" value="$$createVirtualProduct$$"/> + </actionGroup> + <see selector="{{AdminDataGridTableSection.dataGridNoData}}" userInput="We couldn't find any records." stepKey="assertDataGridNoDataMessage1"/> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchGiftCardOnBackend"> + <argument name="product" value="$$createApiGiftCard$$"/> + </actionGroup> + <see selector="{{AdminDataGridTableSection.dataGridNoData}}" userInput="We couldn't find any records." stepKey="assertDataGridNoDataMessage2"/> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchDownloadableProductOnBackend"> + <argument name="product" value="$$createDownloadableProduct$$"/> + </actionGroup> + <see selector="{{AdminDataGridTableSection.dataGridNoData}}" userInput="We couldn't find any records." stepKey="assertDataGridNoDataMessage3"/> + </test> +</tests> diff --git a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml index edcc70a82396d..680b1265ec558 100644 --- a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml +++ b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml @@ -18,5 +18,6 @@ <!--Specific cell e.g. {{Section.gridCell('1', 'Name')}}--> <element name="gridCell" type="text" selector="//tr[{{row}}]//td[count(//div[@data-role='grid-wrapper']//tr//th[contains(., '{{column}}')]/preceding-sibling::th) +1 ]" parameterized="true"/> <element name="rowViewAction" type="button" selector=".data-grid tbody > tr:nth-of-type({{row}}) .action-menu-item" parameterized="true" timeout="30"/> + <element name="dataGridNoData" type="block" selector=".data-grid-tr-no-data td"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/_data/catalog_products.csv b/dev/tests/acceptance/tests/_data/catalog_products.csv new file mode 100644 index 0000000000000..c3be232ee8601 --- /dev/null +++ b/dev/tests/acceptance/tests/_data/catalog_products.csv @@ -0,0 +1,5 @@ +sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,deferred_stock_update,use_config_deferred_stock_update,related_skus,related_position,crosssell_skus,crosssell_position,upsell_skus,upsell_position,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,bundle_shipment_type,configurable_variations,configurable_variation_labels,associated_skus +"Simple Product for Test",,Default,simple,,base,"Simple Product for Test",,,,1,"Taxable Goods","Catalog, Search",123.0000,,,,simple-product-for-test,,,,,,,,,,,,"12/17/18, 8:49 AM","12/17/18, 8:49 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, +"Virtual Product for Test",,Default,virtual,,base,"Virtual Product for Test",,,0.0000,1,"Taxable Goods","Catalog, Search",99.9900,,,,virtual-product-for-test,,,,,,,,,,,,"12/17/18, 8:49 AM","12/17/18, 8:49 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, +"Api Gift Card for Test",,Default,giftcard,,base,"Api Gift Card for Test","API Product Description5c17b791672531","API Product Short Description5c17b791672a11",,1,,"Catalog, Search",,,,,api-gift-card-for-test,,,,,,,,,,,,"12/17/18, 8:49 AM","12/17/18, 8:49 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, +"Api Downloadable Product for Test",,Default,downloadable,,base,"Api Downloadable Product for Test","API Product Description5c17b791672532","API Product Short Description5c17b791672a12",,1,"Taxable Goods","Catalog, Search",123.0000,,,,api-downloadable-product-for-test,,,,,,,,,,,,"12/17/18, 8:49 AM","12/17/18, 8:49 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, From 89ff91c507758762696f1f6cac26d1934d614bd5 Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Tue, 18 Dec 2018 14:15:53 +0200 Subject: [PATCH 13/50] MAGETWO-97034: Import Products with Delete Entities --- .../AdminImportProductsWithDeleteEntitiesTest.xml | 11 +---------- dev/tests/acceptance/tests/_data/catalog_products.csv | 7 +++---- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml index 805c7141bfdff..c3412fa3fbc69 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml @@ -34,11 +34,6 @@ <field key="name">Api Gift Card for Test</field> <field key="sku">Api Gift Card for Test</field> </createData> - <!-- Create Downloadable product --> - <createData entity="ApiDownloadableProduct" stepKey="createDownloadableProduct"> - <field key="name">Api Downloadable Product for Test</field> - <field key="sku">Api Downloadable Product for Test</field> - </createData> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> @@ -55,7 +50,7 @@ <click selector="{{AdminImportMainSection.importButton}}" stepKey="clickImportButton"/> <waitForAjaxLoad stepKey="waitForFileToImportProcessed1"/> <see selector="{{AdminMessagesSection.successMessage}}" userInput="Import successfully done" stepKey="assertSuccessMessage"/> - <see selector="{{AdminImportMainSection.noticeMessage}}" userInput="Created: 0, Updated: 0, Deleted: 4" stepKey="assertNoticeMessage"/> + <see selector="{{AdminImportMainSection.noticeMessage}}" userInput="Created: 0, Updated: 0, Deleted: 3" stepKey="assertNoticeMessage"/> <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchSimpleProductOnBackend"> <argument name="product" value="$$createSimpleProduct$$"/> </actionGroup> @@ -68,9 +63,5 @@ <argument name="product" value="$$createApiGiftCard$$"/> </actionGroup> <see selector="{{AdminDataGridTableSection.dataGridNoData}}" userInput="We couldn't find any records." stepKey="assertDataGridNoDataMessage2"/> - <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchDownloadableProductOnBackend"> - <argument name="product" value="$$createDownloadableProduct$$"/> - </actionGroup> - <see selector="{{AdminDataGridTableSection.dataGridNoData}}" userInput="We couldn't find any records." stepKey="assertDataGridNoDataMessage3"/> </test> </tests> diff --git a/dev/tests/acceptance/tests/_data/catalog_products.csv b/dev/tests/acceptance/tests/_data/catalog_products.csv index c3be232ee8601..c6f6e03db8436 100644 --- a/dev/tests/acceptance/tests/_data/catalog_products.csv +++ b/dev/tests/acceptance/tests/_data/catalog_products.csv @@ -1,5 +1,4 @@ sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,deferred_stock_update,use_config_deferred_stock_update,related_skus,related_position,crosssell_skus,crosssell_position,upsell_skus,upsell_position,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,bundle_shipment_type,configurable_variations,configurable_variation_labels,associated_skus -"Simple Product for Test",,Default,simple,,base,"Simple Product for Test",,,,1,"Taxable Goods","Catalog, Search",123.0000,,,,simple-product-for-test,,,,,,,,,,,,"12/17/18, 8:49 AM","12/17/18, 8:49 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, -"Virtual Product for Test",,Default,virtual,,base,"Virtual Product for Test",,,0.0000,1,"Taxable Goods","Catalog, Search",99.9900,,,,virtual-product-for-test,,,,,,,,,,,,"12/17/18, 8:49 AM","12/17/18, 8:49 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, -"Api Gift Card for Test",,Default,giftcard,,base,"Api Gift Card for Test","API Product Description5c17b791672531","API Product Short Description5c17b791672a11",,1,,"Catalog, Search",,,,,api-gift-card-for-test,,,,,,,,,,,,"12/17/18, 8:49 AM","12/17/18, 8:49 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, -"Api Downloadable Product for Test",,Default,downloadable,,base,"Api Downloadable Product for Test","API Product Description5c17b791672532","API Product Short Description5c17b791672a12",,1,"Taxable Goods","Catalog, Search",123.0000,,,,api-downloadable-product-for-test,,,,,,,,,,,,"12/17/18, 8:49 AM","12/17/18, 8:49 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, +"Simple Product for Test",,Default,simple,,base,"Simple Product for Test",,,,1,"Taxable Goods","Catalog, Search",123.0000,,,,simple-product-for-test,,,,,,,,,,,,"12/18/18, 5:51 AM","12/18/18, 5:51 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, +"Virtual Product for Test",,Default,virtual,,base,"Virtual Product for Test",,,0.0000,1,"Taxable Goods","Catalog, Search",99.9900,,,,virtual-product-for-test,,,,,,,,,,,,"12/18/18, 5:52 AM","12/18/18, 5:52 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, +"Api Gift Card for Test",,Default,giftcard,,base,"Api Gift Card for Test","API Product Description5c18df63aaebc1","API Product Short Description5c18df63aaf011",,1,,"Catalog, Search",,,,,api-gift-card-for-test,,,,,,,,,,,,"12/18/18, 5:52 AM","12/18/18, 5:52 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, From 116bdb2bac58eb7025c823c8428e6ec13088f027 Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Tue, 18 Dec 2018 16:06:35 +0200 Subject: [PATCH 14/50] MAGETWO-97034: Import Products with Delete Entities --- .../AdminImportProductsWithDeleteEntitiesTest.xml | 12 ++++++------ .../acceptance/tests/_data/catalog_products.csv | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml index c3412fa3fbc69..d65f31b7e5c80 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml @@ -29,10 +29,10 @@ <field key="name">Virtual Product for Test</field> <field key="sku">Virtual Product for Test</field> </createData> - <!--Create Gift Card product--> - <createData entity="ApiGiftCard" stepKey="createApiGiftCard"> - <field key="name">Api Gift Card for Test</field> - <field key="sku">Api Gift Card for Test</field> + <!-- Create Downloadable product --> + <createData entity="ApiDownloadableProduct" stepKey="createDownloadableProduct"> + <field key="name">Api Downloadable Product for Test</field> + <field key="sku">Api Downloadable Product for Test</field> </createData> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> @@ -59,8 +59,8 @@ <argument name="product" value="$$createVirtualProduct$$"/> </actionGroup> <see selector="{{AdminDataGridTableSection.dataGridNoData}}" userInput="We couldn't find any records." stepKey="assertDataGridNoDataMessage1"/> - <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchGiftCardOnBackend"> - <argument name="product" value="$$createApiGiftCard$$"/> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchDownloadableProductOnBackend"> + <argument name="product" value="$$createDownloadableProduct$$"/> </actionGroup> <see selector="{{AdminDataGridTableSection.dataGridNoData}}" userInput="We couldn't find any records." stepKey="assertDataGridNoDataMessage2"/> </test> diff --git a/dev/tests/acceptance/tests/_data/catalog_products.csv b/dev/tests/acceptance/tests/_data/catalog_products.csv index c6f6e03db8436..3b580172d6a05 100644 --- a/dev/tests/acceptance/tests/_data/catalog_products.csv +++ b/dev/tests/acceptance/tests/_data/catalog_products.csv @@ -1,4 +1,4 @@ sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,deferred_stock_update,use_config_deferred_stock_update,related_skus,related_position,crosssell_skus,crosssell_position,upsell_skus,upsell_position,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,bundle_shipment_type,configurable_variations,configurable_variation_labels,associated_skus -"Simple Product for Test",,Default,simple,,base,"Simple Product for Test",,,,1,"Taxable Goods","Catalog, Search",123.0000,,,,simple-product-for-test,,,,,,,,,,,,"12/18/18, 5:51 AM","12/18/18, 5:51 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, -"Virtual Product for Test",,Default,virtual,,base,"Virtual Product for Test",,,0.0000,1,"Taxable Goods","Catalog, Search",99.9900,,,,virtual-product-for-test,,,,,,,,,,,,"12/18/18, 5:52 AM","12/18/18, 5:52 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, -"Api Gift Card for Test",,Default,giftcard,,base,"Api Gift Card for Test","API Product Description5c18df63aaebc1","API Product Short Description5c18df63aaf011",,1,,"Catalog, Search",,,,,api-gift-card-for-test,,,,,,,,,,,,"12/18/18, 5:52 AM","12/18/18, 5:52 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, +"Simple Product for Test",,Default,simple,,base,"Simple Product for Test",,,,1,"Taxable Goods","Catalog, Search",123.0000,,,,simple-product-for-test,,,,,,,,,,,,"12/18/18, 7:50 AM","12/18/18, 7:50 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, +"Virtual Product for Test",,Default,virtual,,base,"Virtual Product for Test",,,0.0000,1,"Taxable Goods","Catalog, Search",99.9900,,,,virtual-product-for-test,,,,,,,,,,,,"12/18/18, 7:51 AM","12/18/18, 7:51 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, +"Api Downloadable Product for Test",,Default,downloadable,,base,"Api Downloadable Product for Test","API Product Description5c18fb47982621","API Product Short Description5c18fb47982e21",,1,"Taxable Goods","Catalog, Search",123.0000,,,,api-downloadable-product-for-test,,,,,,,,,,,,"12/18/18, 7:51 AM","12/18/18, 7:51 AM",,,"Block after Info Column",,,,,,,,,,,,,,1000.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,, From 5702c3adfa2ae38e8d2e3818cfa724d62e14951b Mon Sep 17 00:00:00 2001 From: Mariana Lashch <mlashch@magento.com> Date: Tue, 18 Dec 2018 17:20:09 +0200 Subject: [PATCH 15/50] MAGETWO-96379: Cart Price Rule grid count and pagination is wrong - fix CheckTierPricingOfProductsTest --- .../Mftf/Test/CheckTierPricingOfProductsTest.xml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml index 281bad4e49591..c93f0394cdf71 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml @@ -108,6 +108,10 @@ </actionGroup> <actionGroup ref="ClearProductsFilterActionGroup" stepKey="ClearProductsFilterActionGroup"/> + <!--Flush cache--> + <magentoCLI command="cache:flush" stepKey="cleanCache"/> + + <!--Edit customer info--> <actionGroup ref="OpenEditCustomerFromAdminActionGroup" stepKey="OpenEditCustomerFrom"> <argument name="customer" value="$$customer$$"/> @@ -318,13 +322,17 @@ <deleteData createDataKey="category" stepKey="deleteCategory"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> <createData entity="DefaultConfigCatalogPrice" stepKey="defaultConfigCatalogPrice"/> - <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="DeleteWebsite"> - <argument name="websiteName" value="secondWebsite"/> - </actionGroup> <actionGroup ref="DeleteCartPriceRuleByName" stepKey="cleanUpRule"> <argument name="ruleName" value="ship"/> </actionGroup> + <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="DeleteWebsite"> + <argument name="websiteName" value="secondWebsite"/> + </actionGroup> <actionGroup ref="logout" stepKey="logout"/> + + <!--Do reindex and flush cache--> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> </after> </test> </tests> From 36531bc5a182cbd2039f114f93ddc3391fe42e02 Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Wed, 19 Dec 2018 14:40:36 +0200 Subject: [PATCH 16/50] MAGETWO-97034: Import Products with Delete Entities --- .../Test/Mftf/Section/AdminMessagesSection.xml | 1 + .../Test/Mftf/Section/AdminImportMainSection.xml | 1 - ...=> AdminImportProductsWithDeleteBehaviorTest.xml} | 12 +++++------- .../Test/Mftf/Section/AdminDataGridTableSection.xml | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) rename app/code/Magento/ImportExport/Test/Mftf/Test/{AdminImportProductsWithDeleteEntitiesTest.xml => AdminImportProductsWithDeleteBehaviorTest.xml} (81%) diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminMessagesSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminMessagesSection.xml index b1350d5dcc1d7..88e740d689cdd 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminMessagesSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminMessagesSection.xml @@ -12,5 +12,6 @@ <element name="success" type="text" selector="#messages div.message-success"/> <element name="nthSuccess" type="text" selector=".message.message-success.success:nth-of-type({{n}})>div" parameterized="true"/> <element name="error" type="text" selector="#messages div.message-error"/> + <element name="notice" type="text" selector=".message.message-notice.notice"/> </section> </sections> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Section/AdminImportMainSection.xml b/app/code/Magento/ImportExport/Test/Mftf/Section/AdminImportMainSection.xml index 365aca53b4dc0..2ce6b1e35777f 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Section/AdminImportMainSection.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Section/AdminImportMainSection.xml @@ -13,6 +13,5 @@ <element name="importBehavior" type="select" selector="#basic_behavior"/> <element name="selectFileToImport" type="input" selector="#import_file"/> <element name="importButton" type="button" selector="#import_validation_container button" timeout="30"/> - <element name="noticeMessage" type="text" selector="#import_validation_messages .message.message-notice.notice"/> </section> </sections> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteBehaviorTest.xml similarity index 81% rename from app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml rename to app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteBehaviorTest.xml index d65f31b7e5c80..4cbb0603d9073 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteEntitiesTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteBehaviorTest.xml @@ -8,7 +8,7 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="AdminImportProductsWithDeleteEntitiesTest"> + <test name="AdminImportProductsWithDeleteBehaviorTest"> <annotations> <description value="Verify Magento native import products with delete behavior."/> <stories value="Verify Magento native import products with delete behavior."/> @@ -46,22 +46,20 @@ <selectOption selector="{{AdminImportMainSection.importBehavior}}" userInput="Delete" stepKey="selectDeleteOption"/> <attachFile selector="{{AdminImportMainSection.selectFileToImport}}" userInput="catalog_products.csv" stepKey="attachFileForImport"/> <click selector="{{AdminImportHeaderSection.checkDataButton}}" stepKey="clickCheckDataButton"/> - <waitForAjaxLoad stepKey="waitForFileToImportProcessed"/> <click selector="{{AdminImportMainSection.importButton}}" stepKey="clickImportButton"/> - <waitForAjaxLoad stepKey="waitForFileToImportProcessed1"/> <see selector="{{AdminMessagesSection.successMessage}}" userInput="Import successfully done" stepKey="assertSuccessMessage"/> - <see selector="{{AdminImportMainSection.noticeMessage}}" userInput="Created: 0, Updated: 0, Deleted: 3" stepKey="assertNoticeMessage"/> + <see selector="{{AdminMessagesSection.notice}}" userInput="Created: 0, Updated: 0, Deleted: 3" stepKey="assertNotice"/> <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchSimpleProductOnBackend"> <argument name="product" value="$$createSimpleProduct$$"/> </actionGroup> - <see selector="{{AdminDataGridTableSection.dataGridNoData}}" userInput="We couldn't find any records." stepKey="assertDataGridNoDataMessage"/> + <see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="assertDataGridEmptyMessage"/> <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchVirtualProductOnBackend"> <argument name="product" value="$$createVirtualProduct$$"/> </actionGroup> - <see selector="{{AdminDataGridTableSection.dataGridNoData}}" userInput="We couldn't find any records." stepKey="assertDataGridNoDataMessage1"/> + <see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="assertDataGridEmptyMessage1"/> <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchDownloadableProductOnBackend"> <argument name="product" value="$$createDownloadableProduct$$"/> </actionGroup> - <see selector="{{AdminDataGridTableSection.dataGridNoData}}" userInput="We couldn't find any records." stepKey="assertDataGridNoDataMessage2"/> + <see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="assertDataGridEmptyMessage2"/> </test> </tests> diff --git a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml index 680b1265ec558..a2b7ba8c1ffd5 100644 --- a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml +++ b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml @@ -18,6 +18,6 @@ <!--Specific cell e.g. {{Section.gridCell('1', 'Name')}}--> <element name="gridCell" type="text" selector="//tr[{{row}}]//td[count(//div[@data-role='grid-wrapper']//tr//th[contains(., '{{column}}')]/preceding-sibling::th) +1 ]" parameterized="true"/> <element name="rowViewAction" type="button" selector=".data-grid tbody > tr:nth-of-type({{row}}) .action-menu-item" parameterized="true" timeout="30"/> - <element name="dataGridNoData" type="block" selector=".data-grid-tr-no-data td"/> + <element name="dataGridEmpty" type="block" selector=".data-grid-tr-no-data td"/> </section> </sections> From 2e5607181545d6d89f20cc6cc7e9f0f6a348bbe2 Mon Sep 17 00:00:00 2001 From: Mariana Lashch <mlashch@magento.com> Date: Wed, 19 Dec 2018 16:23:57 +0200 Subject: [PATCH 17/50] MAGETWO-96379: Cart Price Rule grid count and pagination is wrong - add selector check --- .../SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml index 3d2682bf55713..14d3a734408db 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Section/AdminCartPriceRulesSection.xml @@ -17,5 +17,6 @@ <element name="rowByIndex" type="text" selector="tr[data-role='row']:nth-of-type({{var1}})" parameterized="true" timeout="30"/> <element name="rulesRow" type="text" selector="//tr[@data-role='row']"/> <element name="pageCurrent" type="text" selector="//label[@for='promo_quote_grid_page-current']"/> + <element name="totalCount" type="text" selector="span[data-ui-id*='grid-total-count']"/> </section> </sections> From 573f74764a23877866ae7627fc43884164668899 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Wed, 19 Dec 2018 18:30:59 +0200 Subject: [PATCH 18/50] MAGETWO-97235: Not all sizes are available in the layered navigation (on Sample Data) with ElasticSearch --- .../CatalogSearch/Model/Layer/Filter/Attribute.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Filter/Attribute.php b/app/code/Magento/CatalogSearch/Model/Layer/Filter/Attribute.php index 7aac6e98fc044..7b239d84bf962 100644 --- a/app/code/Magento/CatalogSearch/Model/Layer/Filter/Attribute.php +++ b/app/code/Magento/CatalogSearch/Model/Layer/Filter/Attribute.php @@ -91,12 +91,10 @@ protected function _getItemsData() return $this->itemDataBuilder->build(); } - $productSize = $productCollection->getSize(); - $options = $attribute->getFrontend() ->getSelectOptions(); foreach ($options as $option) { - $this->buildOptionData($option, $isAttributeFilterable, $optionsFacetedData, $productSize); + $this->buildOptionData($option, $isAttributeFilterable, $optionsFacetedData); } return $this->itemDataBuilder->build(); @@ -108,17 +106,16 @@ protected function _getItemsData() * @param array $option * @param boolean $isAttributeFilterable * @param array $optionsFacetedData - * @param int $productSize * @return void */ - private function buildOptionData($option, $isAttributeFilterable, $optionsFacetedData, $productSize) + private function buildOptionData($option, $isAttributeFilterable, $optionsFacetedData) { $value = $this->getOptionValue($option); if ($value === false) { return; } $count = $this->getOptionCount($value, $optionsFacetedData); - if ($isAttributeFilterable && (!$this->isOptionReducesResults($count, $productSize) || $count === 0)) { + if ($isAttributeFilterable && $count === 0) { return; } From ffc99e5f057215ed9b4dae0017e359bbc9646427 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Wed, 19 Dec 2018 18:45:52 +0200 Subject: [PATCH 19/50] MAGETWO-97235: Not all sizes are available in the layered navigation (on Sample Data) with ElasticSearch --- .../Test/Unit/Model/Layer/Filter/AttributeTest.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Layer/Filter/AttributeTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Layer/Filter/AttributeTest.php index abc0fdd1069fe..69e2c33d02d1a 100644 --- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Layer/Filter/AttributeTest.php +++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Layer/Filter/AttributeTest.php @@ -321,10 +321,6 @@ public function testGetItemsWithoutApply() ->method('build') ->will($this->returnValue($builtData)); - $this->fulltextCollection->expects($this->once()) - ->method('getSize') - ->will($this->returnValue(50)); - $expectedFilterItems = [ $this->createFilterItem(0, $builtData[0]['label'], $builtData[0]['value'], $builtData[0]['count']), $this->createFilterItem(1, $builtData[1]['label'], $builtData[1]['value'], $builtData[1]['count']), @@ -383,9 +379,6 @@ public function testGetItemsOnlyWithResults() $this->fulltextCollection->expects($this->once()) ->method('getFacetedData') ->willReturn($facetedData); - $this->fulltextCollection->expects($this->once()) - ->method('getSize') - ->will($this->returnValue(50)); $this->itemDataBuilder->expects($this->once()) ->method('addItemData') From 08754f065a68b84ad0090a4a2ec0eb1c581ef999 Mon Sep 17 00:00:00 2001 From: bshevchenko <1408sheva@gmail.com> Date: Thu, 20 Dec 2018 12:00:46 +0200 Subject: [PATCH 20/50] MAGETWO-96706: Cart Price Rule with related Banner for specific Customer Segment is persisted under long-term --- .../Cms/Test/Mftf/Section/StorefrontCMSPageSection.xml | 1 - .../ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml | 2 +- .../VerifySubscribedNewsletterDisplayedActionGroup.xml | 2 +- ...anageSection.xml => StorefrontNewsletterManageSection.xml} | 4 ++-- .../Test/Mftf/ActionGroup/AdminCartPriceRuleActionGroup.xml | 4 ++-- 5 files changed, 6 insertions(+), 7 deletions(-) rename app/code/Magento/Newsletter/Test/Mftf/Section/{StorFrontNewsletterManageSection.xml => StorefrontNewsletterManageSection.xml} (86%) diff --git a/app/code/Magento/Cms/Test/Mftf/Section/StorefrontCMSPageSection.xml b/app/code/Magento/Cms/Test/Mftf/Section/StorefrontCMSPageSection.xml index b0262c18f1002..280c7dfd8263e 100644 --- a/app/code/Magento/Cms/Test/Mftf/Section/StorefrontCMSPageSection.xml +++ b/app/code/Magento/Cms/Test/Mftf/Section/StorefrontCMSPageSection.xml @@ -14,6 +14,5 @@ <element name="mainTitle" type="text" selector="#maincontent .page-title"/> <element name="mainContent" type="text" selector="#maincontent"/> <element name="footerTop" type="text" selector="footer.page-footer"/> - <element name="bannerImage" type="block" selector=".banner-items img"/> </section> </sections> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml index 94a47bcb6b1bc..c3ccab53a7636 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml @@ -11,7 +11,7 @@ <arguments> <argument name="Customer" defaultValue="CustomerEntityOne"/> </arguments> - <amOnPage stepKey="amOnStorefrontPage" url="/"/> + <amOnPage stepKey="amOnStorefrontPage" url="{{StorefrontHomePage.url}}"/> <waitForPageLoad stepKey="waitForStorefrontPage"/> <click stepKey="clickOnCreateAccountLink" selector="{{StorefrontPanelHeaderSection.createAnAccountLink}}"/> <fillField stepKey="fillFirstName" userInput="{{Customer.firstname}}" selector="{{StorefrontCustomerCreateFormSection.firstnameField}}"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/VerifySubscribedNewsletterDisplayedActionGroup.xml b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/VerifySubscribedNewsletterDisplayedActionGroup.xml index de63fd34c62b4..8414a1231f922 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/VerifySubscribedNewsletterDisplayedActionGroup.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/VerifySubscribedNewsletterDisplayedActionGroup.xml @@ -26,7 +26,7 @@ </actionGroup> <!--Check Subscribed Newsletter via StoreFront--> - <actionGroup name="checkSubscribedNewsletterActionGroup"> + <actionGroup name="CheckSubscribedNewsletterActionGroup"> <amOnPage url="{{StorefrontNewsletterManagePage.url}}" stepKey="goToNewsletterManage"/> <seeElement selector="{{StorefrontNewsletterManageSection.subscriptionChecked}}" stepKey="checkSubscribedNewsletter"/> </actionGroup> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Section/StorFrontNewsletterManageSection.xml b/app/code/Magento/Newsletter/Test/Mftf/Section/StorefrontNewsletterManageSection.xml similarity index 86% rename from app/code/Magento/Newsletter/Test/Mftf/Section/StorFrontNewsletterManageSection.xml rename to app/code/Magento/Newsletter/Test/Mftf/Section/StorefrontNewsletterManageSection.xml index 4685e2b9a1ec1..7d4c9e476b777 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Section/StorFrontNewsletterManageSection.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Section/StorefrontNewsletterManageSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontNewsletterManageSection"> - <element name="subscriptionCheckbox" type="checkbox" selector="input#subscription" /> - <element name="subscriptionChecked" type="checkbox" selector="input#subscription[checked='checked']" /> + <element name="subscriptionCheckbox" type="checkbox" selector="#subscription" /> + <element name="subscriptionChecked" type="checkbox" selector="#subscription[checked='checked']" /> </section> </sections> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCartPriceRuleActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCartPriceRuleActionGroup.xml index 541f745a6c941..33bbeff73864f 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCartPriceRuleActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCartPriceRuleActionGroup.xml @@ -18,11 +18,11 @@ </actionGroup> <!--Set Subtotal condition for Customer Segment--> - <actionGroup name="setCartAttributeConditionForCartPriceRuleActionGroup"> + <actionGroup name="SetCartAttributeConditionForCartPriceRuleActionGroup"> <arguments> <argument name="attributeName" type="string"/> <argument name="operatorType" defaultValue="is" type="string"/> - <argument name="value" defaultValue="100" type="string"/> + <argument name="value" type="string"/> </arguments> <scrollTo selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" stepKey="scrollToActionTab"/> <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeaderOpen}}" From dbb0a3131281d23ca348dfade923969270288d57 Mon Sep 17 00:00:00 2001 From: Yevhen Sentiabov <isentiabov@magento.com> Date: Thu, 20 Dec 2018 12:30:19 +0200 Subject: [PATCH 21/50] MAGETWO-96379: Cart Price Rule grid count and pagination is wrong - Fixed incorrect steps order --- .../Test/Mftf/Test/CheckTierPricingOfProductsTest.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml index 281bad4e49591..c6a557d1cafdc 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml @@ -317,13 +317,13 @@ <deleteData createDataKey="product4" stepKey="deleteProduct4"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="cleanUpRule"> + <argument name="ruleName" value="ship"/> + </actionGroup> <createData entity="DefaultConfigCatalogPrice" stepKey="defaultConfigCatalogPrice"/> <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="DeleteWebsite"> <argument name="websiteName" value="secondWebsite"/> </actionGroup> - <actionGroup ref="DeleteCartPriceRuleByName" stepKey="cleanUpRule"> - <argument name="ruleName" value="ship"/> - </actionGroup> <actionGroup ref="logout" stepKey="logout"/> </after> </test> From 760fb2ef14512cb6c322992dd2fb6eeb1dce6963 Mon Sep 17 00:00:00 2001 From: bshevchenko <1408sheva@gmail.com> Date: Thu, 20 Dec 2018 14:58:20 +0200 Subject: [PATCH 22/50] MAGETWO-96706: Cart Price Rule with related Banner for specific Customer Segment is persisted under long-term cookie --- .../ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml index c3ccab53a7636..76acf6e865963 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml @@ -11,8 +11,7 @@ <arguments> <argument name="Customer" defaultValue="CustomerEntityOne"/> </arguments> - <amOnPage stepKey="amOnStorefrontPage" url="{{StorefrontHomePage.url}}"/> - <waitForPageLoad stepKey="waitForStorefrontPage"/> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage"/> <click stepKey="clickOnCreateAccountLink" selector="{{StorefrontPanelHeaderSection.createAnAccountLink}}"/> <fillField stepKey="fillFirstName" userInput="{{Customer.firstname}}" selector="{{StorefrontCustomerCreateFormSection.firstnameField}}"/> <fillField stepKey="fillLastName" userInput="{{Customer.lastname}}" selector="{{StorefrontCustomerCreateFormSection.lastnameField}}"/> From c60a0c98c233c5afa43b6e5d7ac226ab70663590 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 20 Dec 2018 17:35:33 +0200 Subject: [PATCH 23/50] MAGETWO-97247: Impossible to enable shared catalog through cli command --- .../Command/ConfigSet/DefaultProcessor.php | 44 +++- app/code/Magento/Config/Model/Config.php | 72 ++++-- .../Config/Test/Unit/Model/ConfigTest.php | 217 ++++++++++-------- app/code/Magento/Store/etc/di.xml | 1 + app/etc/di.xml | 7 + .../Magento/Framework/App/ScopeDefault.php | 4 +- 6 files changed, 221 insertions(+), 124 deletions(-) diff --git a/app/code/Magento/Config/Console/Command/ConfigSet/DefaultProcessor.php b/app/code/Magento/Config/Console/Command/ConfigSet/DefaultProcessor.php index d7d513bfad423..34b8afb7ef144 100644 --- a/app/code/Magento/Config/Console/Command/ConfigSet/DefaultProcessor.php +++ b/app/code/Magento/Config/Console/Command/ConfigSet/DefaultProcessor.php @@ -7,17 +7,20 @@ use Magento\Config\App\Config\Type\System; use Magento\Config\Console\Command\ConfigSetCommand; +use Magento\Config\Model\Config\Factory as ConfigFactory; use Magento\Framework\App\Config\ConfigPathResolver; use Magento\Framework\App\DeploymentConfig; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\ScopeResolverPool; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Config\Model\PreparedValueFactory; -use Magento\Framework\App\Config\Value; /** * Processes default flow of config:set command. + * * This processor saves the value of configuration into database. * - * {@inheritdoc} + * @inheritdoc * @api * @since 100.2.0 */ @@ -44,26 +47,44 @@ class DefaultProcessor implements ConfigSetProcessorInterface */ private $preparedValueFactory; + /** + * @var ScopeResolverPool + */ + private $scopeResolverPool; + + /** + * @var ConfigFactory + */ + private $configFactory; + /** * @param PreparedValueFactory $preparedValueFactory The factory for prepared value * @param DeploymentConfig $deploymentConfig The deployment configuration reader * @param ConfigPathResolver $configPathResolver The resolver for configuration paths according to source type + * @param ScopeResolverPool|null $scopeResolverPool + * @param ConfigFactory|null $configFactory */ public function __construct( PreparedValueFactory $preparedValueFactory, DeploymentConfig $deploymentConfig, - ConfigPathResolver $configPathResolver + ConfigPathResolver $configPathResolver, + ScopeResolverPool $scopeResolverPool = null, + ConfigFactory $configFactory = null ) { $this->preparedValueFactory = $preparedValueFactory; $this->deploymentConfig = $deploymentConfig; $this->configPathResolver = $configPathResolver; + + $this->scopeResolverPool = $scopeResolverPool ?? ObjectManager::getInstance()->get(ScopeResolverPool::class); + $this->configFactory = $configFactory ?? ObjectManager::getInstance()->get(ConfigFactory::class); } /** * Processes database flow of config:set command. + * * Requires installed application. * - * {@inheritdoc} + * @inheritdoc * @since 100.2.0 */ public function process($path, $value, $scope, $scopeCode) @@ -78,12 +99,15 @@ public function process($path, $value, $scope, $scopeCode) } try { - /** @var Value $backendModel */ - $backendModel = $this->preparedValueFactory->create($path, $value, $scope, $scopeCode); - if ($backendModel instanceof Value) { - $resourceModel = $backendModel->getResource(); - $resourceModel->save($backendModel); - } + $resolvedScope = $this->scopeResolverPool->get($scope) + ->getScope($scopeCode); + $config = $this->configFactory->create([ + 'scope' => $resolvedScope->getScopeType(), + 'scope_id' => $resolvedScope->getId(), + 'scope_code' => $resolvedScope->getCode(), + ]); + $config->setDataByPath($path, $value); + $config->save(); } catch (\Exception $exception) { throw new CouldNotSaveException(__('%1', $exception->getMessage()), $exception); } diff --git a/app/code/Magento/Config/Model/Config.php b/app/code/Magento/Config/Model/Config.php index a9c400c46643d..66b0112f5cef6 100644 --- a/app/code/Magento/Config/Model/Config.php +++ b/app/code/Magento/Config/Model/Config.php @@ -9,15 +9,31 @@ use Magento\Config\Model\Config\Structure\Element\Group; use Magento\Config\Model\Config\Structure\Element\Field; use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\ScopeInterface; +use Magento\Framework\App\ScopeResolverPool; +use Magento\Store\Model\ScopeInterface as StoreScopeInterface; /** * Backend config model * * Used to save configuration + * * @author Magento Core Team <core@magentocommerce.com> * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @api * @since 100.0.2 + * @method string getSection() + * @method void setSection(string $section) + * @method string getWebsite() + * @method void setWebsite(string $website) + * @method string getStore() + * @method void setStore(string $store) + * @method string getScope() + * @method void setScope(string $scope) + * @method int getScopeId() + * @method void setScopeId(int $scopeId) + * @method string getScopeCode() + * @method void setScopeCode(string $scopeCode) */ class Config extends \Magento\Framework\DataObject { @@ -87,6 +103,11 @@ class Config extends \Magento\Framework\DataObject */ private $settingChecker; + /** + * @var ScopeResolverPool + */ + private $scopeResolverPool; + /** * @param \Magento\Framework\App\Config\ReinitableConfigInterface $config * @param \Magento\Framework\Event\ManagerInterface $eventManager @@ -97,6 +118,7 @@ class Config extends \Magento\Framework\DataObject * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param Config\Reader\Source\Deployed\SettingChecker|null $settingChecker * @param array $data + * @param ScopeResolverPool|null $scopeResolverPool */ public function __construct( \Magento\Framework\App\Config\ReinitableConfigInterface $config, @@ -107,7 +129,8 @@ public function __construct( \Magento\Framework\App\Config\ValueFactory $configValueFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, SettingChecker $settingChecker = null, - array $data = [] + array $data = [], + ScopeResolverPool $scopeResolverPool = null ) { parent::__construct($data); $this->_eventManager = $eventManager; @@ -117,7 +140,8 @@ public function __construct( $this->_configLoader = $configLoader; $this->_configValueFactory = $configValueFactory; $this->_storeManager = $storeManager; - $this->settingChecker = $settingChecker ?: ObjectManager::getInstance()->get(SettingChecker::class); + $this->settingChecker = $settingChecker ?? ObjectManager::getInstance()->get(SettingChecker::class); + $this->scopeResolverPool = $scopeResolverPool ?? ObjectManager::getInstance()->get(ScopeResolverPool::class); } /** @@ -505,9 +529,8 @@ public function setDataByPath($path, $value) } /** - * Get scope name and scopeId + * Resolve scope data * - * @todo refactor to scope resolver * @return void */ private function initScope() @@ -522,24 +545,33 @@ private function initScope() $this->setStore(''); } - if ($this->getStore()) { - $scope = 'stores'; - $store = $this->_storeManager->getStore($this->getStore()); - $scopeId = (int)$store->getId(); - $scopeCode = $store->getCode(); - } elseif ($this->getWebsite()) { - $scope = 'websites'; - $website = $this->_storeManager->getWebsite($this->getWebsite()); - $scopeId = (int)$website->getId(); - $scopeCode = $website->getCode(); + if ($this->getScope() && $this->getScopeId() && $this->getScopeCode()) { + $scope = $this->scopeResolverPool->get($this->getScope()) + ->getScope($this->getScopeId()); + if (StoreScopeInterface::SCOPE_WEBSITE === $scope->getScopeType()) { + $this->setWebsite($scope->getId()); + } elseif (StoreScopeInterface::SCOPE_STORE === $scope->getScopeType()) { + $this->setStore($scope->getId()); + } } else { - $scope = 'default'; - $scopeId = 0; - $scopeCode = ''; + switch (true) { + case $this->getStore(): + $scope = $this->scopeResolverPool->get(StoreScopeInterface::SCOPE_STORE) + ->getScope($this->getStore()); + break; + case $this->getWebsite(): + $scope = $this->scopeResolverPool->get(StoreScopeInterface::SCOPE_WEBSITE) + ->getScope($this->getWebsite()); + break; + default: + $scope = $this->scopeResolverPool->get(ScopeInterface::SCOPE_DEFAULT) + ->getScope(0); + break; + } + $this->setScope($scope->getScopeType()); + $this->setScopeId($scope->getId()); + $this->setScopeCode($scope->getCode()); } - $this->setScope($scope); - $this->setScopeId($scopeId); - $this->setScopeCode($scopeCode); } /** diff --git a/app/code/Magento/Config/Test/Unit/Model/ConfigTest.php b/app/code/Magento/Config/Test/Unit/Model/ConfigTest.php index d0568f48ded1e..ab0070a3a88e7 100644 --- a/app/code/Magento/Config/Test/Unit/Model/ConfigTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/ConfigTest.php @@ -5,6 +5,8 @@ */ namespace Magento\Config\Test\Unit\Model; +use PHPUnit\Framework\MockObject\MockObject; + /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -13,130 +15,150 @@ class ConfigTest extends \PHPUnit\Framework\TestCase /** * @var \Magento\Config\Model\Config */ - protected $_model; + private $model; + + /** + * @var \Magento\Framework\Event\ManagerInterface|MockObject + */ + private $eventManagerMock; + + /** + * @var \Magento\Config\Model\Config\Structure\Reader|MockObject + */ + private $structureReaderMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\DB\TransactionFactory|MockObject */ - protected $_eventManagerMock; + private $transFactoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Config\ReinitableConfigInterface|MockObject */ - protected $_structureReaderMock; + private $appConfigMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Config\Model\Config\Loader|MockObject */ - protected $_transFactoryMock; + private $configLoaderMock; /** - * @var \Magento\Framework\App\Config\ReinitableConfigInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Config\ValueFactory|MockObject */ - protected $_appConfigMock; + private $dataFactoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Store\Model\StoreManagerInterface|MockObject */ - protected $_applicationMock; + private $storeManager; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Config\Model\Config\Structure|MockObject */ - protected $_configLoaderMock; + private $configStructure; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Config\Model\Config\Reader\Source\Deployed\SettingChecker|MockObject */ - protected $_dataFactoryMock; + private $settingsChecker; /** - * @var \Magento\Store\Model\StoreManagerInterface + * @var \Magento\Framework\App\ScopeResolverPool|MockObject */ - protected $_storeManager; + private $scopeResolverPool; /** - * @var \Magento\Config\Model\Config\Structure + * @var \Magento\Framework\App\ScopeResolverInterface|MockObject */ - protected $_configStructure; + private $scopeResolver; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\ScopeInterface|MockObject */ - private $_settingsChecker; + private $scope; protected function setUp() { - $this->_eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); - $this->_structureReaderMock = $this->createPartialMock( + $this->eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); + $this->structureReaderMock = $this->createPartialMock( \Magento\Config\Model\Config\Structure\Reader::class, ['getConfiguration'] ); - $this->_configStructure = $this->createMock(\Magento\Config\Model\Config\Structure::class); + $this->configStructure = $this->createMock(\Magento\Config\Model\Config\Structure::class); - $this->_structureReaderMock->expects( + $this->structureReaderMock->expects( $this->any() )->method( 'getConfiguration' )->will( - $this->returnValue($this->_configStructure) + $this->returnValue($this->configStructure) ); - $this->_transFactoryMock = $this->createPartialMock( + $this->transFactoryMock = $this->createPartialMock( \Magento\Framework\DB\TransactionFactory::class, ['create', 'addObject'] ); - $this->_appConfigMock = $this->createMock(\Magento\Framework\App\Config\ReinitableConfigInterface::class); - $this->_configLoaderMock = $this->createPartialMock( + $this->appConfigMock = $this->createMock(\Magento\Framework\App\Config\ReinitableConfigInterface::class); + $this->configLoaderMock = $this->createPartialMock( \Magento\Config\Model\Config\Loader::class, ['getConfigByPath'] ); - $this->_dataFactoryMock = $this->createMock(\Magento\Framework\App\Config\ValueFactory::class); + $this->dataFactoryMock = $this->createMock(\Magento\Framework\App\Config\ValueFactory::class); - $this->_storeManager = $this->getMockForAbstractClass(\Magento\Store\Model\StoreManagerInterface::class); + $this->storeManager = $this->createMock(\Magento\Store\Model\StoreManagerInterface::class); - $this->_settingsChecker = $this + $this->settingsChecker = $this ->createMock(\Magento\Config\Model\Config\Reader\Source\Deployed\SettingChecker::class); - $this->_model = new \Magento\Config\Model\Config( - $this->_appConfigMock, - $this->_eventManagerMock, - $this->_configStructure, - $this->_transFactoryMock, - $this->_configLoaderMock, - $this->_dataFactoryMock, - $this->_storeManager, - $this->_settingsChecker + $this->scopeResolverPool = $this->createMock(\Magento\Framework\App\ScopeResolverPool::class); + $this->scopeResolver = $this->createMock(\Magento\Framework\App\ScopeResolverInterface::class); + $this->scopeResolverPool->method('get') + ->willReturn($this->scopeResolver); + $this->scope = $this->createMock(\Magento\Framework\App\ScopeInterface::class); + $this->scopeResolver->method('getScope') + ->willReturn($this->scope); + + $this->model = new \Magento\Config\Model\Config( + $this->appConfigMock, + $this->eventManagerMock, + $this->configStructure, + $this->transFactoryMock, + $this->configLoaderMock, + $this->dataFactoryMock, + $this->storeManager, + $this->settingsChecker, + [], + $this->scopeResolverPool ); } public function testSaveDoesNotDoAnythingIfGroupsAreNotPassed() { - $this->_configLoaderMock->expects($this->never())->method('getConfigByPath'); - $this->_model->save(); + $this->configLoaderMock->expects($this->never())->method('getConfigByPath'); + $this->model->save(); } public function testSaveEmptiesNonSetArguments() { - $this->_structureReaderMock->expects($this->never())->method('getConfiguration'); - $this->assertNull($this->_model->getSection()); - $this->assertNull($this->_model->getWebsite()); - $this->assertNull($this->_model->getStore()); - $this->_model->save(); - $this->assertSame('', $this->_model->getSection()); - $this->assertSame('', $this->_model->getWebsite()); - $this->assertSame('', $this->_model->getStore()); + $this->structureReaderMock->expects($this->never())->method('getConfiguration'); + $this->assertNull($this->model->getSection()); + $this->assertNull($this->model->getWebsite()); + $this->assertNull($this->model->getStore()); + $this->model->save(); + $this->assertSame('', $this->model->getSection()); + $this->assertSame('', $this->model->getWebsite()); + $this->assertSame('', $this->model->getStore()); } public function testSaveToCheckAdminSystemConfigChangedSectionEvent() { $transactionMock = $this->createMock(\Magento\Framework\DB\Transaction::class); - $this->_transFactoryMock->expects($this->any())->method('create')->will($this->returnValue($transactionMock)); + $this->transFactoryMock->expects($this->any())->method('create')->will($this->returnValue($transactionMock)); - $this->_configLoaderMock->expects($this->any())->method('getConfigByPath')->will($this->returnValue([])); + $this->configLoaderMock->expects($this->any())->method('getConfigByPath')->will($this->returnValue([])); - $this->_eventManagerMock->expects( + $this->eventManagerMock->expects( $this->at(0) )->method( 'dispatch' @@ -145,7 +167,7 @@ public function testSaveToCheckAdminSystemConfigChangedSectionEvent() $this->arrayHasKey('website') ); - $this->_eventManagerMock->expects( + $this->eventManagerMock->expects( $this->at(0) )->method( 'dispatch' @@ -154,20 +176,20 @@ public function testSaveToCheckAdminSystemConfigChangedSectionEvent() $this->arrayHasKey('store') ); - $this->_model->setGroups(['1' => ['data']]); - $this->_model->save(); + $this->model->setGroups(['1' => ['data']]); + $this->model->save(); } public function testDoNotSaveReadOnlyFields() { $transactionMock = $this->createMock(\Magento\Framework\DB\Transaction::class); - $this->_transFactoryMock->expects($this->any())->method('create')->will($this->returnValue($transactionMock)); + $this->transFactoryMock->expects($this->any())->method('create')->will($this->returnValue($transactionMock)); - $this->_settingsChecker->expects($this->any())->method('isReadOnly')->will($this->returnValue(true)); - $this->_configLoaderMock->expects($this->any())->method('getConfigByPath')->will($this->returnValue([])); + $this->settingsChecker->expects($this->any())->method('isReadOnly')->will($this->returnValue(true)); + $this->configLoaderMock->expects($this->any())->method('getConfigByPath')->will($this->returnValue([])); - $this->_model->setGroups(['1' => ['fields' => ['key' => ['data']]]]); - $this->_model->setSection('section'); + $this->model->setGroups(['1' => ['fields' => ['key' => ['data']]]]); + $this->model->setSection('section'); $group = $this->createMock(\Magento\Config\Model\Config\Structure\Element\Group::class); $group->method('getPath')->willReturn('section/1'); @@ -176,15 +198,15 @@ public function testDoNotSaveReadOnlyFields() $field->method('getGroupPath')->willReturn('section/1'); $field->method('getId')->willReturn('key'); - $this->_configStructure->expects($this->at(0)) + $this->configStructure->expects($this->at(0)) ->method('getElement') ->with('section/1') ->will($this->returnValue($group)); - $this->_configStructure->expects($this->at(1)) + $this->configStructure->expects($this->at(1)) ->method('getElement') ->with('section/1') ->will($this->returnValue($group)); - $this->_configStructure->expects($this->at(2)) + $this->configStructure->expects($this->at(2)) ->method('getElement') ->with('section/1/key') ->will($this->returnValue($field)); @@ -193,28 +215,28 @@ public function testDoNotSaveReadOnlyFields() \Magento\Framework\App\Config\Value::class, ['addData'] ); - $this->_dataFactoryMock->expects($this->any())->method('create')->will($this->returnValue($backendModel)); + $this->dataFactoryMock->expects($this->any())->method('create')->will($this->returnValue($backendModel)); - $this->_transFactoryMock->expects($this->never())->method('addObject'); + $this->transFactoryMock->expects($this->never())->method('addObject'); $backendModel->expects($this->never())->method('addData'); - $this->_model->save(); + $this->model->save(); } public function testSaveToCheckScopeDataSet() { $transactionMock = $this->createMock(\Magento\Framework\DB\Transaction::class); - $this->_transFactoryMock->expects($this->any())->method('create')->will($this->returnValue($transactionMock)); + $this->transFactoryMock->expects($this->any())->method('create')->will($this->returnValue($transactionMock)); - $this->_configLoaderMock->expects($this->any())->method('getConfigByPath')->will($this->returnValue([])); + $this->configLoaderMock->expects($this->any())->method('getConfigByPath')->will($this->returnValue([])); - $this->_eventManagerMock->expects($this->at(0)) + $this->eventManagerMock->expects($this->at(0)) ->method('dispatch') ->with( $this->equalTo('admin_system_config_changed_section_section'), $this->arrayHasKey('website') ); - $this->_eventManagerMock->expects($this->at(0)) + $this->eventManagerMock->expects($this->at(0)) ->method('dispatch') ->with( $this->equalTo('admin_system_config_changed_section_section'), @@ -228,36 +250,47 @@ public function testSaveToCheckScopeDataSet() $field->method('getGroupPath')->willReturn('section/1'); $field->method('getId')->willReturn('key'); - $this->_configStructure->expects($this->at(0)) + $this->configStructure->expects($this->at(0)) ->method('getElement') ->with('section/1') ->will($this->returnValue($group)); - $this->_configStructure->expects($this->at(1)) + $this->configStructure->expects($this->at(1)) ->method('getElement') ->with('section/1') ->will($this->returnValue($group)); - $this->_configStructure->expects($this->at(2)) + $this->configStructure->expects($this->at(2)) ->method('getElement') ->with('section/1/key') ->will($this->returnValue($field)); - $this->_configStructure->expects($this->at(3)) + $this->configStructure->expects($this->at(3)) ->method('getElement') ->with('section/1') ->will($this->returnValue($group)); - $this->_configStructure->expects($this->at(4)) + $this->configStructure->expects($this->at(4)) ->method('getElement') ->with('section/1/key') ->will($this->returnValue($field)); + $this->scopeResolver->expects($this->atLeastOnce()) + ->method('getScope') + ->with('1') + ->willReturn($this->scope); + $this->scope->expects($this->atLeastOnce()) + ->method('getScopeType') + ->willReturn('website'); + $this->scope->expects($this->atLeastOnce()) + ->method('getId') + ->willReturn(1); + $this->scope->expects($this->atLeastOnce()) + ->method('getCode') + ->willReturn('website_code'); $website = $this->createMock(\Magento\Store\Model\Website::class); - $website->expects($this->any())->method('getCode')->will($this->returnValue('website_code')); - $this->_storeManager->expects($this->any())->method('getWebsite')->will($this->returnValue($website)); - $this->_storeManager->expects($this->any())->method('getWebsites')->will($this->returnValue([$website])); - $this->_storeManager->expects($this->any())->method('isSingleStoreMode')->will($this->returnValue(true)); + $this->storeManager->expects($this->any())->method('getWebsites')->will($this->returnValue([$website])); + $this->storeManager->expects($this->any())->method('isSingleStoreMode')->will($this->returnValue(true)); - $this->_model->setWebsite('website'); - $this->_model->setSection('section'); - $this->_model->setGroups(['1' => ['fields' => ['key' => ['data']]]]); + $this->model->setWebsite('1'); + $this->model->setSection('section'); + $this->model->setGroups(['1' => ['fields' => ['key' => ['data']]]]); $backendModel = $this->createPartialMock( \Magento\Framework\App\Config\Value::class, @@ -269,8 +302,8 @@ public function testSaveToCheckScopeDataSet() 'field' => 'key', 'groups' => [1 => ['fields' => ['key' => ['data']]]], 'group_id' => null, - 'scope' => 'websites', - 'scope_id' => 0, + 'scope' => 'website', + 'scope_id' => 1, 'scope_code' => 'website_code', 'field_config' => null, 'fieldset_data' => ['key' => null], @@ -280,16 +313,16 @@ public function testSaveToCheckScopeDataSet() ->with('section/1/key') ->will($this->returnValue($backendModel)); - $this->_dataFactoryMock->expects($this->any())->method('create')->will($this->returnValue($backendModel)); + $this->dataFactoryMock->expects($this->any())->method('create')->will($this->returnValue($backendModel)); - $this->_model->save(); + $this->model->save(); } public function testSetDataByPath() { $value = 'value'; $path = '<section>/<group>/<field>'; - $this->_model->setDataByPath($path, $value); + $this->model->setDataByPath($path, $value); $expected = [ 'section' => '<section>', 'groups' => [ @@ -300,7 +333,7 @@ public function testSetDataByPath() ], ], ]; - $this->assertSame($expected, $this->_model->getData()); + $this->assertSame($expected, $this->model->getData()); } /** @@ -309,7 +342,7 @@ public function testSetDataByPath() */ public function testSetDataByPathEmpty() { - $this->_model->setDataByPath('', 'value'); + $this->model->setDataByPath('', 'value'); } /** @@ -324,7 +357,7 @@ public function testSetDataByPathWrongDepth($path, $expectedException) $this->expectException('\UnexpectedValueException'); $this->expectExceptionMessage($expectedException); $value = 'value'; - $this->_model->setDataByPath($path, $value); + $this->model->setDataByPath($path, $value); } /** diff --git a/app/code/Magento/Store/etc/di.xml b/app/code/Magento/Store/etc/di.xml index be005264b7bbf..defe0694d018d 100644 --- a/app/code/Magento/Store/etc/di.xml +++ b/app/code/Magento/Store/etc/di.xml @@ -236,6 +236,7 @@ <type name="Magento\Framework\App\ScopeResolverPool"> <arguments> <argument name="scopeResolvers" xsi:type="array"> + <item name="default" xsi:type="object">Magento\Framework\App\ScopeResolver</item> <item name="store" xsi:type="object">Magento\Store\Model\Resolver\Store</item> <item name="stores" xsi:type="object">Magento\Store\Model\Resolver\Store</item> <item name="group" xsi:type="object">Magento\Store\Model\Resolver\Group</item> diff --git a/app/etc/di.xml b/app/etc/di.xml index ceccee04a8bc4..6cf169c1d2277 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -1749,4 +1749,11 @@ </argument> </arguments> </type> + <type name="Magento\Framework\App\ScopeResolverPool"> + <arguments> + <argument name="scopeResolvers" xsi:type="array"> + <item name="default" xsi:type="object">Magento\Framework\App\ScopeResolver</item> + </argument> + </arguments> + </type> </config> diff --git a/lib/internal/Magento/Framework/App/ScopeDefault.php b/lib/internal/Magento/Framework/App/ScopeDefault.php index 2ea62387145bf..e62d19f9ffbb4 100644 --- a/lib/internal/Magento/Framework/App/ScopeDefault.php +++ b/lib/internal/Magento/Framework/App/ScopeDefault.php @@ -17,7 +17,7 @@ class ScopeDefault implements ScopeInterface */ public function getCode() { - return 'default'; + return ''; } /** @@ -27,7 +27,7 @@ public function getCode() */ public function getId() { - return 1; + return 0; } /** From 148b5056f5c5250a9cebe9bd2d773bbb4ba6b2e3 Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Fri, 21 Dec 2018 11:58:37 +0200 Subject: [PATCH 24/50] MAGETWO-97278: Incorrect use of cookies for customer --- .../StorefrontCustomerActionGroup.xml | 18 ++ .../Section/StorefrontPanelHeaderSection.xml | 3 + .../Persistent/Block/Header/Additional.php | 55 +++- .../Persistent/CustomerData/Persistent.php | 72 +++++ .../Magento/Persistent/Model/Observer.php | 7 +- .../Plugin/PersistentCustomerContext.php | 41 +++ .../StorefrontCustomerActionGroup.xml | 22 ++ .../StorefrontCustomerSignInFormSection.xml | 14 + ...omeMessageAfterCustomerIsLoggedOutTest.xml | 79 ++++++ .../Test/Unit/Block/Header/AdditionalTest.php | 246 +++--------------- .../Test/Unit/Model/ObserverTest.php | 25 +- app/code/Magento/Persistent/etc/di.xml | 3 + .../Magento/Persistent/etc/frontend/di.xml | 14 + .../Persistent/etc/frontend/sections.xml | 13 + .../view/frontend/requirejs-config.js | 14 + .../view/frontend/templates/additional.phtml | 21 ++ .../web/js/view/additional-welcome.js | 55 ++++ .../web/js/view/customer-data-mixin.js | 51 ++++ .../Section/AdminCreditMemoTotalSection.xml | 3 +- .../Mftf/Section/AdminInvoiceItemsSection.xml | 3 +- .../Mftf/Section/StorefrontHeaderSection.xml | 13 + .../view/frontend/templates/html/header.phtml | 4 +- .../Block/Header/AdditionalTest.php | 4 +- .../Magento/Persistent/Model/ObserverTest.php | 32 +-- 24 files changed, 531 insertions(+), 281 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerActionGroup.xml create mode 100644 app/code/Magento/Persistent/CustomerData/Persistent.php create mode 100644 app/code/Magento/Persistent/Model/Plugin/PersistentCustomerContext.php create mode 100644 app/code/Magento/Persistent/Test/Mftf/ActionGroup/StorefrontCustomerActionGroup.xml create mode 100644 app/code/Magento/Persistent/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml create mode 100644 app/code/Magento/Persistent/Test/Mftf/Test/StorefrontCorrectWelcomeMessageAfterCustomerIsLoggedOutTest.xml create mode 100644 app/code/Magento/Persistent/etc/frontend/sections.xml create mode 100644 app/code/Magento/Persistent/view/frontend/requirejs-config.js create mode 100644 app/code/Magento/Persistent/view/frontend/templates/additional.phtml create mode 100644 app/code/Magento/Persistent/view/frontend/web/js/view/additional-welcome.js create mode 100644 app/code/Magento/Persistent/view/frontend/web/js/view/customer-data-mixin.js create mode 100644 app/code/Magento/Theme/Test/Mftf/Section/StorefrontHeaderSection.xml diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerActionGroup.xml new file mode 100644 index 0000000000000..fc5c1b881752e --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerActionGroup.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="CustomerLogoutStorefrontByMenuItemsActionGroup"> + <conditionalClick selector="{{StorefrontPanelHeaderSection.customerWelcome}}" + dependentSelector="{{StorefrontPanelHeaderSection.customerWelcomeMenu}}" + visible="false" + stepKey="clickHeaderCustomerMenuButton" /> + <click selector="{{StorefrontPanelHeaderSection.customerLogoutLink}}" stepKey="clickSignOutButton" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml index a0c83f5bc491b..1955c6a417ba9 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontPanelHeaderSection.xml @@ -12,5 +12,8 @@ <element name="WelcomeMessage" type="text" selector=".greet.welcome span"/> <element name="createAnAccountLink" type="select" selector=".panel.header li:nth-child(3)" timeout="30"/> <element name="notYouLink" type="button" selector=".greet.welcome span a"/> + <element name="customerWelcome" type="text" selector=".panel.header .customer-welcome"/> + <element name="customerWelcomeMenu" type="text" selector=".panel.header .customer-welcome .customer-menu"/> + <element name="customerLogoutLink" type="text" selector=".panel.header .customer-welcome .customer-menu .authorization-link a" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Persistent/Block/Header/Additional.php b/app/code/Magento/Persistent/Block/Header/Additional.php index c740f5a3469fb..f82a0e7250bf9 100644 --- a/app/code/Magento/Persistent/Block/Header/Additional.php +++ b/app/code/Magento/Persistent/Block/Header/Additional.php @@ -5,6 +5,10 @@ */ namespace Magento\Persistent\Block\Header; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Serialize\Serializer\Json; +use Magento\Persistent\Helper\Data; + /** * Remember Me block * @@ -30,20 +34,37 @@ class Additional extends \Magento\Framework\View\Element\Html\Link protected $customerRepository; /** - * Constructor - * + * @var string + */ + protected $_template = 'Magento_Persistent::additional.phtml'; + + /** + * @var Json + */ + private $jsonSerializer; + + /** + * @var Data + */ + private $persistentHelper; + + /** * @param \Magento\Framework\View\Element\Template\Context $context * @param \Magento\Customer\Helper\View $customerViewHelper * @param \Magento\Persistent\Helper\Session $persistentSessionHelper * @param \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository * @param array $data + * @param Json|null $jsonSerializer + * @param Data|null $persistentHelper */ public function __construct( \Magento\Framework\View\Element\Template\Context $context, \Magento\Customer\Helper\View $customerViewHelper, \Magento\Persistent\Helper\Session $persistentSessionHelper, \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository, - array $data = [] + array $data = [], + Json $jsonSerializer = null, + Data $persistentHelper = null ) { $this->isScopePrivate = true; $this->_customerViewHelper = $customerViewHelper; @@ -51,6 +72,8 @@ public function __construct( $this->customerRepository = $customerRepository; parent::__construct($context, $data); $this->_isScopePrivate = true; + $this->jsonSerializer = $jsonSerializer ?: ObjectManager::getInstance()->get(Json::class); + $this->persistentHelper = $persistentHelper ?: ObjectManager::getInstance()->get(Data::class); } /** @@ -64,17 +87,27 @@ public function getHref() } /** - * Render additional header html + * Get customer id. * - * @return string + * @return int */ - protected function _toHtml() + public function getCustomerId(): int { - if ($this->_persistentSessionHelper->getSession()->getCustomerId()) { - return '<span><a ' . $this->getLinkAttributes() . ' >' . __('Not you?') - . '</a></span>'; - } + return $this->_persistentSessionHelper->getSession()->getCustomerId(); + } - return ''; + /** + * Get persistent config. + * + * @return string + */ + public function getConfig(): string + { + return + $this->jsonSerializer->serialize( + [ + 'expirationLifetime' => $this->persistentHelper->getLifeTime(), + ] + ); } } diff --git a/app/code/Magento/Persistent/CustomerData/Persistent.php b/app/code/Magento/Persistent/CustomerData/Persistent.php new file mode 100644 index 0000000000000..5800e4e7aeeb5 --- /dev/null +++ b/app/code/Magento/Persistent/CustomerData/Persistent.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Persistent\CustomerData; + +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\CustomerData\SectionSourceInterface; +use Magento\Customer\Helper\View; +use Magento\Persistent\Helper\Session; + +/** + * Customer persistent section + */ +class Persistent implements SectionSourceInterface +{ + /** + * @var Session + */ + private $persistentSession; + + /** + * @var View + */ + private $customerViewHelper; + + /** + * @var CustomerRepositoryInterface + */ + private $customerRepository; + + /** + * @param Session $persistentSession + * @param View $customerViewHelper + * @param CustomerRepositoryInterface $customerRepository + */ + public function __construct( + Session $persistentSession, + View $customerViewHelper, + CustomerRepositoryInterface $customerRepository + ) { + $this->persistentSession = $persistentSession; + $this->customerViewHelper = $customerViewHelper; + $this->customerRepository = $customerRepository; + } + + /** + * Get data. + * + * @return array + */ + public function getSectionData(): array + { + if (!$this->persistentSession->isPersistent()) { + return []; + } + + $customerId = $this->persistentSession->getSession()->getCustomerId(); + if (!$customerId) { + return []; + } + + $customer = $this->customerRepository->getById($customerId); + + return [ + 'fullname' => $this->customerViewHelper->getCustomerName($customer), + ]; + } +} diff --git a/app/code/Magento/Persistent/Model/Observer.php b/app/code/Magento/Persistent/Model/Observer.php index 53fe5f95531e1..81c2870071a2e 100644 --- a/app/code/Magento/Persistent/Model/Observer.php +++ b/app/code/Magento/Persistent/Model/Observer.php @@ -86,13 +86,8 @@ public function __construct( */ public function emulateWelcomeBlock($block) { - $customerName = $this->_customerViewHelper->getCustomerName( - $this->customerRepository->getById($this->_persistentSession->getSession()->getCustomerId()) - ); + $block->setWelcome(' '); - $this->_applyAccountLinksPersistentData(); - $welcomeMessage = __('Welcome, %1!', $customerName); - $block->setWelcome($welcomeMessage); return $this; } diff --git a/app/code/Magento/Persistent/Model/Plugin/PersistentCustomerContext.php b/app/code/Magento/Persistent/Model/Plugin/PersistentCustomerContext.php new file mode 100644 index 0000000000000..4ddb1040e0db6 --- /dev/null +++ b/app/code/Magento/Persistent/Model/Plugin/PersistentCustomerContext.php @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Persistent\Model\Plugin; + +/** + * Plugin for Magento\Framework\App\Http\Context to create new page cache variation for persistent session. + */ +class PersistentCustomerContext +{ + /** + * Persistent session. + * + * @var \Magento\Persistent\Helper\Session + */ + private $persistentSession; + + /** + * @param \Magento\Persistent\Helper\Session $persistentSession + */ + public function __construct( + \Magento\Persistent\Helper\Session $persistentSession + ) { + $this->persistentSession = $persistentSession; + } + + /** + * Sets appropriate header if customer session is persistent. + * + * @param \Magento\Framework\App\Http\Context $subject + * @return mixed + */ + public function beforeGetVaryString(\Magento\Framework\App\Http\Context $subject) + { + if ($this->persistentSession->isPersistent()) { + $subject->setValue('PERSISTENT', 1, 0); + } + } +} diff --git a/app/code/Magento/Persistent/Test/Mftf/ActionGroup/StorefrontCustomerActionGroup.xml b/app/code/Magento/Persistent/Test/Mftf/ActionGroup/StorefrontCustomerActionGroup.xml new file mode 100644 index 0000000000000..293fa04d80462 --- /dev/null +++ b/app/code/Magento/Persistent/Test/Mftf/ActionGroup/StorefrontCustomerActionGroup.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="CustomerLoginOnStorefrontWithRememberMeChecked" extends="LoginToStorefrontActionGroup"> + <checkOption selector="{{StorefrontCustomerSignInFormSection.rememberMe}}" + before="clickSignInAccountButton" + stepKey="checkRememberMe"/> + </actionGroup> + + <actionGroup name="CustomerLoginOnStorefrontWithRememberMeUnChecked" extends="LoginToStorefrontActionGroup"> + <uncheckOption selector="{{StorefrontCustomerSignInFormSection.rememberMe}}" + before="clickSignInAccountButton" + stepKey="unCheckRememberMe"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Persistent/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml b/app/code/Magento/Persistent/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml new file mode 100644 index 0000000000000..c2220c33a6052 --- /dev/null +++ b/app/code/Magento/Persistent/Test/Mftf/Section/StorefrontCustomerSignInFormSection.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="StorefrontCustomerSignInFormSection"> + <element name="rememberMe" type="checkbox" selector="[name='persistent_remember_me']"/> + </section> +</sections> diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontCorrectWelcomeMessageAfterCustomerIsLoggedOutTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontCorrectWelcomeMessageAfterCustomerIsLoggedOutTest.xml new file mode 100644 index 0000000000000..7fffc6c2b0d37 --- /dev/null +++ b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontCorrectWelcomeMessageAfterCustomerIsLoggedOutTest.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="StorefrontCorrectWelcomeMessageAfterCustomerIsLoggedOutTest"> + <annotations> + <features value="Persistent"/> + <stories value="MAGETWO-97278 - Incorrect use of cookies for customer"/> + <title value="Checking welcome message for persistent customer after logout"/> + <description value="Checking welcome message for persistent customer after logout"/> + <severity value="MAJOR"/> + <testCaseId value="MC-10800"/> + <group value="persistent"/> + <group value="customer"/> + </annotations> + <before> + <!--Enable Persistence--> + <createData entity="PersistentConfigEnabled" stepKey="enablePersistent"/> + <createData entity="PersistentLogoutClearDisable" stepKey="persistentLogoutClearDisable"/> + + <!--Create customers--> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + <createData entity="Simple_US_Customer" stepKey="createCustomerForPersistent"> + <field key="firstname">John1</field> + <field key="lastname">Doe1</field> + </createData> + </before> + <after> + <!--Roll back configuration--> + <createData entity="PersistentConfigDefault" stepKey="setDefaultPersistentState"/> + <createData entity="PersistentLogoutClearEnabled" stepKey="persistentLogoutClearEnabled"/> + + <!-- Logout customer on Storefront--> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogoutStorefront"/> + <!--Delete customers--> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <deleteData createDataKey="createCustomerForPersistent" stepKey="deleteCustomerForPersistent"/> + </after> + <!--Login as a Customer with remember me unchecked--> + <actionGroup ref="CustomerLoginOnStorefrontWithRememberMeUnChecked" stepKey="loginToStorefrontAccountWithRememberMeUnchecked"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + + <!--Check customer name and last name in welcome message--> + <seeCurrentUrlMatches regex="~/customer/account/~" stepKey="seeCustomerAccountPageUrl"/> + <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" + selector="{{StorefrontHeaderSection.welcomeMessage}}" + stepKey="seeLoggedInCustomerWelcomeMessage"/> + <!--Logout and check default welcome message--> + <actionGroup ref="CustomerLogoutStorefrontByMenuItemsActionGroup" stepKey="storefrontCustomerLogout"/> + <seeCurrentUrlMatches regex="~/customer/account/logoutSuccess/~" wait="5" stepKey="seeCustomerSignOutPageUrl"/> + <see userInput="Default welcome msg!" + selector="{{StorefrontHeaderSection.welcomeMessage}}" + stepKey="seeDefaultWelcomeMessage"/> + + <!--Login as a Customer with remember me checked--> + <actionGroup ref="CustomerLoginOnStorefrontWithRememberMeChecked" stepKey="loginToStorefrontAccountWithRememberMeChecked"> + <argument name="Customer" value="$$createCustomerForPersistent$$"/> + </actionGroup> + <!--Check customer name and last name in welcome message--> + <seeCurrentUrlMatches regex="~/customer/account/~" stepKey="seeCustomerAccountPageUrl1"/> + <see userInput="Welcome, $$createCustomerForPersistent.firstname$$ $$createCustomerForPersistent.lastname$$!" + selector="{{StorefrontHeaderSection.welcomeMessage}}" + stepKey="seeLoggedInCustomerWelcomeMessage1"/> + + <!--Logout and check persistent customer welcome message--> + <actionGroup ref="CustomerLogoutStorefrontByMenuItemsActionGroup" stepKey="storefrontCustomerLogout1"/> + <seeCurrentUrlMatches regex="~/customer/account/logoutSuccess/~" wait="5" stepKey="seeCustomerSignOutPageUrl1"/> + <see userInput="Welcome, $$createCustomerForPersistent.firstname$$ $$createCustomerForPersistent.lastname$$! Not you?" + selector="{{StorefrontHeaderSection.welcomeMessage}}" + stepKey="seePersistentWelcomeMessage"/> + </test> +</tests> diff --git a/app/code/Magento/Persistent/Test/Unit/Block/Header/AdditionalTest.php b/app/code/Magento/Persistent/Test/Unit/Block/Header/AdditionalTest.php index b88b02ab4cfb5..407dad05c3baf 100644 --- a/app/code/Magento/Persistent/Test/Unit/Block/Header/AdditionalTest.php +++ b/app/code/Magento/Persistent/Test/Unit/Block/Header/AdditionalTest.php @@ -34,44 +34,14 @@ class AdditionalTest extends \PHPUnit\Framework\TestCase protected $contextMock; /** - * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Serialize\Serializer\Json|\PHPUnit_Framework_MockObject_MockObject */ - protected $eventManagerMock; + private $jsonSerializerMock; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Persistent\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */ - protected $scopeConfigMock; - - /** - * @var \Magento\Framework\App\Cache\StateInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $cacheStateMock; - - /** - * @var \Magento\Framework\App\CacheInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $cacheMock; - - /** - * @var \Magento\Framework\Session\SidResolverInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $sidResolverMock; - - /** - * @var \Magento\Framework\Session\SessionManagerInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $sessionMock; - - /** - * @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject - */ - protected $escaperMock; - - /** - * @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $urlBuilderMock; + private $persistentHelperMock; /** * @var \Magento\Persistent\Block\Header\Additional @@ -93,17 +63,7 @@ protected function setUp() { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->contextMock = $this->createPartialMock(\Magento\Framework\View\Element\Template\Context::class, [ - 'getEventManager', - 'getScopeConfig', - 'getCacheState', - 'getCache', - 'getInlineTranslation', - 'getSidResolver', - 'getSession', - 'getEscaper', - 'getUrlBuilder' - ]); + $this->contextMock = $this->createPartialMock(\Magento\Framework\View\Element\Template\Context::class, []); $this->customerViewHelperMock = $this->createMock(\Magento\Customer\Helper\View::class); $this->persistentSessionHelperMock = $this->createPartialMock( \Magento\Persistent\Helper\Session::class, @@ -119,103 +79,14 @@ protected function setUp() ['getById'] ); - $this->eventManagerMock = $this->getMockForAbstractClass( - \Magento\Framework\Event\ManagerInterface::class, - [], - '', - false, - true, - true, - ['dispatch'] - ); - $this->scopeConfigMock = $this->getMockForAbstractClass( - \Magento\Framework\App\Config\ScopeConfigInterface::class, - [], - '', - false, - true, - true, - ['getValue'] - ); - $this->cacheStateMock = $this->getMockForAbstractClass( - \Magento\Framework\App\Cache\StateInterface::class, - [], - '', - false, - true, - true, - ['isEnabled'] + $this->jsonSerializerMock = $this->createPartialMock( + \Magento\Framework\Serialize\Serializer\Json::class, + ['serialize'] ); - $this->cacheMock = $this->getMockForAbstractClass( - \Magento\Framework\App\CacheInterface::class, - [], - '', - false, - true, - true, - ['load'] + $this->persistentHelperMock = $this->createPartialMock( + \Magento\Persistent\Helper\Data::class, + ['getLifeTime'] ); - $this->sidResolverMock = $this->getMockForAbstractClass( - \Magento\Framework\Session\SidResolverInterface::class, - [], - '', - false, - true, - true, - ['getSessionIdQueryParam'] - ); - $this->sessionMock = $this->getMockForAbstractClass( - \Magento\Framework\Session\SessionManagerInterface::class, - [], - '', - false, - true, - true, - ['getSessionId'] - ); - $this->escaperMock = $this->getMockForAbstractClass( - \Magento\Framework\Escaper::class, - [], - '', - false, - true, - true, - ['escapeHtml'] - ); - $this->urlBuilderMock = $this->getMockForAbstractClass( - \Magento\Framework\UrlInterface::class, - [], - '', - false, - true, - true, - ['getUrl'] - ); - - $this->contextMock->expects($this->once()) - ->method('getEventManager') - ->willReturn($this->eventManagerMock); - $this->contextMock->expects($this->once()) - ->method('getScopeConfig') - ->willReturn($this->scopeConfigMock); - $this->contextMock->expects($this->once()) - ->method('getCacheState') - ->willReturn($this->cacheStateMock); - $this->contextMock->expects($this->once()) - ->method('getCache') - ->willReturn($this->cacheMock); - $this->contextMock->expects($this->once()) - ->method('getSidResolver') - ->willReturn($this->sidResolverMock); - $this->contextMock->expects($this->once()) - ->method('getSession') - ->willReturn($this->sessionMock); - $this->contextMock->expects($this->once()) - ->method('getEscaper') - ->willReturn($this->escaperMock); - $this->contextMock->expects($this->once()) - ->method('getUrlBuilder') - ->willReturn($this->urlBuilderMock); $this->additional = $this->objectManager->getObject( \Magento\Persistent\Block\Header\Additional::class, @@ -224,91 +95,48 @@ protected function setUp() 'customerViewHelper' => $this->customerViewHelperMock, 'persistentSessionHelper' => $this->persistentSessionHelperMock, 'customerRepository' => $this->customerRepositoryMock, - 'data' => [] + 'data' => [], + 'jsonSerializer' => $this->jsonSerializerMock, + 'persistentHelper' => $this->persistentHelperMock, ] ); } /** - * Run test toHtml method - * - * @param bool $customerId * @return void - * - * @dataProvider dataProviderToHtml */ - public function testToHtml($customerId) + public function testGetCustomerId(): void { - $cacheData = false; - $idQueryParam = 'id-query-param'; - $sessionId = 'session-id'; - - $this->additional->setData('cache_lifetime', 789); - $this->additional->setData('cache_key', 'cache-key'); - - $this->eventManagerMock->expects($this->at(0)) - ->method('dispatch') - ->with('view_block_abstract_to_html_before', ['block' => $this->additional]); - $this->eventManagerMock->expects($this->at(1)) - ->method('dispatch') - ->with('view_block_abstract_to_html_after'); - $this->scopeConfigMock->expects($this->once()) - ->method('getValue') - ->with( - 'advanced/modules_disable_output/Magento_Persistent', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE - )->willReturn(false); - - // get cache - $this->cacheStateMock->expects($this->at(0)) - ->method('isEnabled') - ->with(\Magento\Persistent\Block\Header\Additional::CACHE_GROUP) - ->willReturn(true); - // save cache - $this->cacheStateMock->expects($this->at(1)) - ->method('isEnabled') - ->with(\Magento\Persistent\Block\Header\Additional::CACHE_GROUP) - ->willReturn(false); - - $this->cacheMock->expects($this->once()) - ->method('load') - ->willReturn($cacheData); - $this->sidResolverMock->expects($this->never()) - ->method('getSessionIdQueryParam') - ->with($this->sessionMock) - ->willReturn($idQueryParam); - $this->sessionMock->expects($this->never()) - ->method('getSessionId') - ->willReturn($sessionId); - - // call protected _toHtml method + $customerId = 1; + /** @var \Magento\Persistent\Model\Session|\PHPUnit_Framework_MockObject_MockObject $sessionMock */ $sessionMock = $this->createPartialMock(\Magento\Persistent\Model\Session::class, ['getCustomerId']); - - $this->persistentSessionHelperMock->expects($this->atLeastOnce()) - ->method('getSession') - ->willReturn($sessionMock); - - $sessionMock->expects($this->atLeastOnce()) + $sessionMock->expects($this->once()) ->method('getCustomerId') ->willReturn($customerId); + $this->persistentSessionHelperMock->expects($this->once()) + ->method('getSession') + ->willReturn($sessionMock); - if ($customerId) { - $this->assertEquals('<span><a >Not you?</a></span>', $this->additional->toHtml()); - } else { - $this->assertEquals('', $this->additional->toHtml()); - } + $this->assertEquals($customerId, $this->additional->getCustomerId()); } /** - * Data provider for dataProviderToHtml method - * - * @return array + * @return void */ - public function dataProviderToHtml() + public function testGetConfig(): void { - return [ - ['customerId' => 2], - ['customerId' => null], - ]; + $lifeTime = 500; + $arrayToSerialize = ['expirationLifetime' => $lifeTime]; + $serializedArray = '{"expirationLifetime":' . $lifeTime . '}'; + + $this->persistentHelperMock->expects($this->once()) + ->method('getLifeTime') + ->willReturn($lifeTime); + $this->jsonSerializerMock->expects($this->once()) + ->method('serialize') + ->with($arrayToSerialize) + ->willReturn($serializedArray); + + $this->assertEquals($serializedArray, $this->additional->getConfig()); } } diff --git a/app/code/Magento/Persistent/Test/Unit/Model/ObserverTest.php b/app/code/Magento/Persistent/Test/Unit/Model/ObserverTest.php index 7008a9eb25e5d..6d4db70adc642 100644 --- a/app/code/Magento/Persistent/Test/Unit/Model/ObserverTest.php +++ b/app/code/Magento/Persistent/Test/Unit/Model/ObserverTest.php @@ -80,31 +80,18 @@ protected function setUp() ); } - public function testEmulateWelcomeBlock() + /** + * @return void + */ + public function testEmulateWelcomeBlock(): void { - $customerId = 1; - $customerName = 'Test Customer Name'; - $welcomeMessage = __('Welcome, %1!', $customerName); - $customerMock = $this->getMockForAbstractClass(\Magento\Customer\Api\Data\CustomerInterface::class); + $welcomeMessage = __(' '); $block = $this->getMockBuilder(\Magento\Framework\View\Element\AbstractBlock::class) ->disableOriginalConstructor() ->setMethods(['setWelcome']) ->getMock(); - $headerAdditionalBlock = $this->getMockBuilder(\Magento\Framework\View\Element\AbstractBlock::class) - ->disableOriginalConstructor() - ->getMock(); - $this->persistentSessionMock->expects($this->once())->method('getSession')->willReturn($this->sessionMock); - $this->sessionMock->expects($this->once())->method('getCustomerId')->willReturn($customerId); - $this->customerRepositoryMock - ->expects($this->once()) - ->method('getById') - ->with($customerId)->willReturn($customerMock); - $this->customerViewHelperMock->expects($this->once())->method('getCustomerName')->willReturn($customerName); - $this->layoutMock->expects($this->once()) - ->method('getBlock') - ->with('header.additional') - ->willReturn($headerAdditionalBlock); $block->expects($this->once())->method('setWelcome')->with($welcomeMessage); + $this->observer->emulateWelcomeBlock($block); } } diff --git a/app/code/Magento/Persistent/etc/di.xml b/app/code/Magento/Persistent/etc/di.xml index f49d4361acb52..c28426b4f25bf 100644 --- a/app/code/Magento/Persistent/etc/di.xml +++ b/app/code/Magento/Persistent/etc/di.xml @@ -12,4 +12,7 @@ <type name="Magento\Customer\CustomerData\Customer"> <plugin name="section_data" type="Magento\Persistent\Model\Plugin\CustomerData" /> </type> + <type name="Magento\Framework\App\Http\Context"> + <plugin name="persistent_page_cache_variation" type="Magento\Persistent\Model\Plugin\PersistentCustomerContext" /> + </type> </config> diff --git a/app/code/Magento/Persistent/etc/frontend/di.xml b/app/code/Magento/Persistent/etc/frontend/di.xml index f976f4de79c21..3c33f8a51c418 100644 --- a/app/code/Magento/Persistent/etc/frontend/di.xml +++ b/app/code/Magento/Persistent/etc/frontend/di.xml @@ -35,4 +35,18 @@ <type name="Magento\Checkout\Model\GuestPaymentInformationManagement"> <plugin name="inject_guest_address_for_nologin" type="Magento\Persistent\Model\Checkout\GuestPaymentInformationManagementPlugin" /> </type> + <type name="Magento\Customer\CustomerData\SectionPoolInterface"> + <arguments> + <argument name="sectionSourceMap" xsi:type="array"> + <item name="persistent" xsi:type="string">Magento\Persistent\CustomerData\Persistent</item> + </argument> + </arguments> + </type> + <type name="Magento\Customer\Block\CustomerData"> + <arguments> + <argument name="expirableSectionNames" xsi:type="array"> + <item name="persistent" xsi:type="string">persistent</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Persistent/etc/frontend/sections.xml b/app/code/Magento/Persistent/etc/frontend/sections.xml new file mode 100644 index 0000000000000..16b44c502fc47 --- /dev/null +++ b/app/code/Magento/Persistent/etc/frontend/sections.xml @@ -0,0 +1,13 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd"> + <action name="persistent/index/unsetCookie"> + <section name="persistent"/> + </action> +</config> diff --git a/app/code/Magento/Persistent/view/frontend/requirejs-config.js b/app/code/Magento/Persistent/view/frontend/requirejs-config.js new file mode 100644 index 0000000000000..e30e07c454be5 --- /dev/null +++ b/app/code/Magento/Persistent/view/frontend/requirejs-config.js @@ -0,0 +1,14 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +var config = { + config: { + mixins: { + 'Magento_Customer/js/customer-data': { + 'Magento_Persistent/js/view/customer-data-mixin': true + } + } + } +}; diff --git a/app/code/Magento/Persistent/view/frontend/templates/additional.phtml b/app/code/Magento/Persistent/view/frontend/templates/additional.phtml new file mode 100644 index 0000000000000..28dce5dc23cc9 --- /dev/null +++ b/app/code/Magento/Persistent/view/frontend/templates/additional.phtml @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +?> +<?php if ($block->getCustomerId()) :?> + <span> + <a <?= /* @escapeNotVerified */ $block->getLinkAttributes()?>><?= $block->escapeHtml(__('Not you?'));?></a> + </span> +<?php endif;?> +<script type="application/javascript"> + window.persistent = <?= /* @noEscape */ $block->getConfig(); ?>; +</script> +<script type="text/x-magento-init"> + { + "li.greet.welcome > span.not-logged-in": { + "Magento_Persistent/js/view/additional-welcome": {} + } + } +</script> diff --git a/app/code/Magento/Persistent/view/frontend/web/js/view/additional-welcome.js b/app/code/Magento/Persistent/view/frontend/web/js/view/additional-welcome.js new file mode 100644 index 0000000000000..7ace6e60d1c39 --- /dev/null +++ b/app/code/Magento/Persistent/view/frontend/web/js/view/additional-welcome.js @@ -0,0 +1,55 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'mage/translate', + 'Magento_Customer/js/customer-data' +], function ($, $t, customerData) { + 'use strict'; + + return { + /** + * Init. + */ + init: function () { + var persistent = customerData.get('persistent'); + + if (persistent().fullname === undefined) { + customerData.get('persistent').subscribe(this.replacePersistentWelcome); + } else { + this.replacePersistentWelcome(); + } + }, + + /** + * Replace welcome message for customer with persistent cookie. + */ + replacePersistentWelcome: function () { + var persistent = customerData.get('persistent'), + welcomeElems; + + if (persistent().fullname !== undefined) { + welcomeElems = $('li.greet.welcome > span.not-logged-in'); + + if (welcomeElems.length) { + $(welcomeElems).each(function () { + var html = $t('Welcome, %1!').replace('%1', persistent().fullname); + + $(this).attr('data-bind', html); + $(this).html(html); + }); + } + } + }, + + /** + * @constructor + */ + 'Magento_Persistent/js/view/additional-welcome': function () { + this.init(); + } + }; +}); diff --git a/app/code/Magento/Persistent/view/frontend/web/js/view/customer-data-mixin.js b/app/code/Magento/Persistent/view/frontend/web/js/view/customer-data-mixin.js new file mode 100644 index 0000000000000..855404c6f6f32 --- /dev/null +++ b/app/code/Magento/Persistent/view/frontend/web/js/view/customer-data-mixin.js @@ -0,0 +1,51 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'jquery', + 'mage/utils/wrapper' +], function ($, wrapper) { + 'use strict'; + + var mixin = { + + /** + * Check if persistent section is expired due to lifetime. + * + * @param {Function} originFn - Original method. + * @return {Array} + */ + getExpiredSectionNames: function (originFn) { + var expiredSections = originFn(), + storage = $.initNamespaceStorage('mage-cache-storage').localStorage, + currentTimestamp = Math.floor(Date.now() / 1000), + persistentIndex = expiredSections.indexOf('persistent'), + persistentLifeTime = 0, + sectionData; + + if (window.persistent !== undefined && window.persistent.expirationLifetime !== undefined) { + persistentLifeTime = window.persistent.expirationLifetime; + } + + if (persistentIndex !== -1) { + sectionData = storage.get('persistent'); + + if (typeof sectionData === 'object' && + sectionData['data_id'] + persistentLifeTime >= currentTimestamp + ) { + expiredSections.splice(persistentIndex, 1); + } + } + + return expiredSections; + } + }; + + /** + * Override default customer-data.getExpiredSectionNames(). + */ + return function (target) { + return wrapper.extend(target, mixin); + }; +}); diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml index 84fcc8fc47dfb..6eb7e9e7d16df 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml @@ -19,7 +19,8 @@ <element name="emailCopy" type="checkbox" selector=".order-totals-actions #send_email"/> <element name="refundStoreCredit" type="checkbox" selector=".order-totals-actions .field-refund-store-credit input[type='checkbox']"/> <element name="submitRefundOffline" type="button" selector=".order-totals-actions button[data-ui-id='order-items-submit-button']" timeout="30"/> + <element name="submitRefundOfflineEnabled" type="button" selector=".order-totals-actions button[data-ui-id='order-items-submit-button'][class='action-default scalable save submit-button primary']" timeout="30"/> <element name="creditMemoItem" type="text" selector="#sales_order_view_tabs_order_creditmemos"/> <element name="viewMemo" type="text" selector="div#sales_order_view_tabs_order_creditmemos_content a.action-menu-item"/> </section> -</sections> \ No newline at end of file +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceItemsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceItemsSection.xml index bc0d1cffd5d3e..03087d8949c2f 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceItemsSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceItemsSection.xml @@ -28,5 +28,6 @@ <element name="discountAmountColumn" type="text" selector=".order-invoice-tables .col-discount .price"/> <element name="totalColumn" type="text" selector=".order-invoice-tables .col-total .price"/> <element name="updateQty" type="button" selector=".order-invoice-tables tfoot button[data-ui-id='order-items-update-button']"/> + <element name="updateQtyEnabled" type="button" selector=".order-invoice-tables tfoot button[data-ui-id='order-items-update-button'][class='action-default scalable update-button']"/> </section> -</sections> \ No newline at end of file +</sections> diff --git a/app/code/Magento/Theme/Test/Mftf/Section/StorefrontHeaderSection.xml b/app/code/Magento/Theme/Test/Mftf/Section/StorefrontHeaderSection.xml new file mode 100644 index 0000000000000..a4088c7a4a0b7 --- /dev/null +++ b/app/code/Magento/Theme/Test/Mftf/Section/StorefrontHeaderSection.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontHeaderSection"> + <element name="welcomeMessage" type="text" selector=".greet.welcome"/> + </section> +</sections> diff --git a/app/code/Magento/Theme/view/frontend/templates/html/header.phtml b/app/code/Magento/Theme/view/frontend/templates/html/header.phtml index 4395cab651de1..1103ae28741c6 100644 --- a/app/code/Magento/Theme/view/frontend/templates/html/header.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/html/header.phtml @@ -15,11 +15,11 @@ $welcomeMessage = $block->getWelcome(); case 'welcome': ?> <li class="greet welcome" data-bind="scope: 'customer'"> <!-- ko if: customer().fullname --> - <span data-bind="text: new String('<?= $block->escapeHtml(__('Welcome, %1!', '%1')) ?>').replace('%1', customer().fullname)"> + <span class="logged-in" data-bind="text: new String('<?= $block->escapeHtml(__('Welcome, %1!', '%1')) ?>').replace('%1', customer().fullname)"> </span> <!-- /ko --> <!-- ko ifnot: customer().fullname --> - <span data-bind='html:"<?= $block->escapeHtml($welcomeMessage) ?>"'></span> + <span class="not-logged-in" data-bind='html:"<?= $block->escapeHtml($welcomeMessage) ?>"'></span> <?= $block->getBlockHtml('header.additional') ?> <!-- /ko --> </li> diff --git a/dev/tests/integration/testsuite/Magento/Persistent/Block/Header/AdditionalTest.php b/dev/tests/integration/testsuite/Magento/Persistent/Block/Header/AdditionalTest.php index fba5354b691d6..2e447e7854a7c 100644 --- a/dev/tests/integration/testsuite/Magento/Persistent/Block/Header/AdditionalTest.php +++ b/dev/tests/integration/testsuite/Magento/Persistent/Block/Header/AdditionalTest.php @@ -56,8 +56,8 @@ public function testToHtml() $this->_customerSession->loginById(1); $translation = __('Not you?'); - $this->assertStringMatchesFormat( - '%A<span>%A<a%Ahref="' . $this->_block->getHref() . '"%A>' . $translation . '</a>%A</span>%A', + $this->assertContains( + '<a href="' . $this->_block->getHref() . '">' . $translation . '</a>', $this->_block->toHtml() ); $this->_customerSession->logout(); diff --git a/dev/tests/integration/testsuite/Magento/Persistent/Model/ObserverTest.php b/dev/tests/integration/testsuite/Magento/Persistent/Model/ObserverTest.php index ecf2cd77a13ff..d0c253fc7a64b 100644 --- a/dev/tests/integration/testsuite/Magento/Persistent/Model/ObserverTest.php +++ b/dev/tests/integration/testsuite/Magento/Persistent/Model/ObserverTest.php @@ -9,7 +9,6 @@ use Magento\Customer\Model\Context; /** - * @magentoDataFixture Magento/Persistent/_files/persistent.php * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ObserverTest extends \PHPUnit\Framework\TestCase @@ -29,11 +28,6 @@ class ObserverTest extends \PHPUnit\Framework\TestCase */ protected $customerRepository; - /** - * @var \Magento\Persistent\Helper\Session - */ - protected $_persistentSessionHelper; - /** * @var \Magento\Framework\ObjectManagerInterface */ @@ -44,11 +38,6 @@ class ObserverTest extends \PHPUnit\Framework\TestCase */ protected $_observer; - /** - * @var \Magento\Customer\Model\Session - */ - protected $_customerSession; - /** * @var \Magento\Checkout\Model\Session | \PHPUnit_Framework_MockObject_MockObject */ @@ -58,8 +47,6 @@ public function setUp() { $this->_objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->_customerSession = $this->_objectManager->get(\Magento\Customer\Model\Session::class); - $this->_customerViewHelper = $this->_objectManager->create( \Magento\Customer\Helper\View::class ); @@ -75,8 +62,6 @@ public function setUp() \Magento\Checkout\Model\Session::class )->disableOriginalConstructor()->setMethods([])->getMock(); - $this->_persistentSessionHelper = $this->_objectManager->create(\Magento\Persistent\Helper\Session::class); - $this->_observer = $this->_objectManager->create( \Magento\Persistent\Model\Observer::class, [ @@ -89,16 +74,11 @@ public function setUp() } /** - * @magentoConfigFixture current_store persistent/options/enabled 1 - * @magentoConfigFixture current_store persistent/options/remember_enabled 1 - * @magentoConfigFixture current_store persistent/options/remember_default 1 * @magentoAppArea frontend * @magentoAppIsolation enabled */ public function testEmulateWelcomeBlock() { - $this->_customerSession->loginById(1); - $httpContext = new \Magento\Framework\App\Http\Context(); $httpContext->setValue(Context::CONTEXT_AUTH, 1, 1); $block = $this->_objectManager->create( @@ -108,15 +88,7 @@ public function testEmulateWelcomeBlock() ] ); $this->_observer->emulateWelcomeBlock($block); - $customerName = $this->_escaper->escapeHtml( - $this->_customerViewHelper->getCustomerName( - $this->customerRepository->getById( - $this->_persistentSessionHelper->getSession()->getCustomerId() - ) - ) - ); - $translation = __('Welcome, %1!', $customerName)->__toString(); - $this->assertStringMatchesFormat('%A' . $translation . '%A', $block->getWelcome()->__toString()); - $this->_customerSession->logout(); + + $this->assertEquals(' ', $block->getWelcome()); } } From 5ebb2f51373d2303c51059c617cb00ea1489e4f4 Mon Sep 17 00:00:00 2001 From: bshevchenko <1408sheva@gmail.com> Date: Fri, 21 Dec 2018 13:22:39 +0200 Subject: [PATCH 25/50] MAGETWO-96706: Cart Price Rule with related Banner for specific Customer Segment is persisted under long-term cookie --- .../Backend/Test/Mftf/Section/AdminMainActionsSection.xml | 2 +- .../VerifySubscribedNewsletterDisplayedActionGroup.xml | 2 +- .../Test/Mftf/Section/StorefrontNewsletterManageSection.xml | 1 - .../SalesRule/Test/Mftf/Data/SalesRuleAddressConditionsData.xml | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminMainActionsSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminMainActionsSection.xml index c6d37291e625f..ef2e5f4216889 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminMainActionsSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminMainActionsSection.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminMainActionsSection"> <element name="save" type="button" selector="#save" timeout="30"/> - <element name="saveAndContinue" type="button" selector="#save_and_continue_edit" timeout="30"/> + <element name="saveAndContinue" type="button" selector="button[id*=save_and_continue]" timeout="30"/> <element name="delete" type="button" selector="#delete" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/VerifySubscribedNewsletterDisplayedActionGroup.xml b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/VerifySubscribedNewsletterDisplayedActionGroup.xml index 8414a1231f922..059f157c407c9 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/VerifySubscribedNewsletterDisplayedActionGroup.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/VerifySubscribedNewsletterDisplayedActionGroup.xml @@ -28,6 +28,6 @@ <!--Check Subscribed Newsletter via StoreFront--> <actionGroup name="CheckSubscribedNewsletterActionGroup"> <amOnPage url="{{StorefrontNewsletterManagePage.url}}" stepKey="goToNewsletterManage"/> - <seeElement selector="{{StorefrontNewsletterManageSection.subscriptionChecked}}" stepKey="checkSubscribedNewsletter"/> + <seeCheckboxIsChecked selector="{{StorefrontNewsletterManageSection.subscriptionCheckbox}}" stepKey="checkSubscribedNewsletter"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Section/StorefrontNewsletterManageSection.xml b/app/code/Magento/Newsletter/Test/Mftf/Section/StorefrontNewsletterManageSection.xml index 7d4c9e476b777..96a944a4952ac 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Section/StorefrontNewsletterManageSection.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Section/StorefrontNewsletterManageSection.xml @@ -10,6 +10,5 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontNewsletterManageSection"> <element name="subscriptionCheckbox" type="checkbox" selector="#subscription" /> - <element name="subscriptionChecked" type="checkbox" selector="#subscription[checked='checked']" /> </section> </sections> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleAddressConditionsData.xml b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleAddressConditionsData.xml index 5e9247825b29a..cc695b347c4fb 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleAddressConditionsData.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleAddressConditionsData.xml @@ -16,6 +16,6 @@ <data key="shippingPostCode">Magento\SalesRule\Model\Rule\Condition\Address|postcode</data> <data key="shippingRegion">Magento\SalesRule\Model\Rule\Condition\Address|region</data> <data key="shippingState">Magento\SalesRule\Model\Rule\Condition\Address|region_id</data> - <data key="ShippingCountry">Magento\SalesRule\Model\Rule\Condition\Address|country_id</data> + <data key="shippingCountry">Magento\SalesRule\Model\Rule\Condition\Address|country_id</data> </entity> </entities> From 069fa71e96537880312658c91523747405af1e00 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Fri, 21 Dec 2018 13:59:17 +0200 Subject: [PATCH 26/50] MAGETWO-97247: Impossible to enable shared catalog through cli command --- .../Command/ConfigSet/DefaultProcessor.php | 16 +---- app/code/Magento/Config/Model/Config.php | 48 +++++++++----- .../ConfigSet/DefaultProcessorTest.php | 64 +++++++------------ 3 files changed, 57 insertions(+), 71 deletions(-) diff --git a/app/code/Magento/Config/Console/Command/ConfigSet/DefaultProcessor.php b/app/code/Magento/Config/Console/Command/ConfigSet/DefaultProcessor.php index 34b8afb7ef144..86ae1f96749df 100644 --- a/app/code/Magento/Config/Console/Command/ConfigSet/DefaultProcessor.php +++ b/app/code/Magento/Config/Console/Command/ConfigSet/DefaultProcessor.php @@ -11,7 +11,6 @@ use Magento\Framework\App\Config\ConfigPathResolver; use Magento\Framework\App\DeploymentConfig; use Magento\Framework\App\ObjectManager; -use Magento\Framework\App\ScopeResolverPool; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Config\Model\PreparedValueFactory; @@ -47,11 +46,6 @@ class DefaultProcessor implements ConfigSetProcessorInterface */ private $preparedValueFactory; - /** - * @var ScopeResolverPool - */ - private $scopeResolverPool; - /** * @var ConfigFactory */ @@ -61,21 +55,18 @@ class DefaultProcessor implements ConfigSetProcessorInterface * @param PreparedValueFactory $preparedValueFactory The factory for prepared value * @param DeploymentConfig $deploymentConfig The deployment configuration reader * @param ConfigPathResolver $configPathResolver The resolver for configuration paths according to source type - * @param ScopeResolverPool|null $scopeResolverPool * @param ConfigFactory|null $configFactory */ public function __construct( PreparedValueFactory $preparedValueFactory, DeploymentConfig $deploymentConfig, ConfigPathResolver $configPathResolver, - ScopeResolverPool $scopeResolverPool = null, ConfigFactory $configFactory = null ) { $this->preparedValueFactory = $preparedValueFactory; $this->deploymentConfig = $deploymentConfig; $this->configPathResolver = $configPathResolver; - $this->scopeResolverPool = $scopeResolverPool ?? ObjectManager::getInstance()->get(ScopeResolverPool::class); $this->configFactory = $configFactory ?? ObjectManager::getInstance()->get(ConfigFactory::class); } @@ -99,12 +90,9 @@ public function process($path, $value, $scope, $scopeCode) } try { - $resolvedScope = $this->scopeResolverPool->get($scope) - ->getScope($scopeCode); $config = $this->configFactory->create([ - 'scope' => $resolvedScope->getScopeType(), - 'scope_id' => $resolvedScope->getId(), - 'scope_code' => $resolvedScope->getCode(), + 'scope' => $scope, + 'scope_code' => $scopeCode, ]); $config->setDataByPath($path, $value); $config->save(); diff --git a/app/code/Magento/Config/Model/Config.php b/app/code/Magento/Config/Model/Config.php index 66b0112f5cef6..8aa7171bd8f72 100644 --- a/app/code/Magento/Config/Model/Config.php +++ b/app/code/Magento/Config/Model/Config.php @@ -119,6 +119,7 @@ class Config extends \Magento\Framework\DataObject * @param Config\Reader\Source\Deployed\SettingChecker|null $settingChecker * @param array $data * @param ScopeResolverPool|null $scopeResolverPool + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( \Magento\Framework\App\Config\ReinitableConfigInterface $config, @@ -529,7 +530,7 @@ public function setDataByPath($path, $value) } /** - * Resolve scope data + * Set scope data * * @return void */ @@ -545,35 +546,48 @@ private function initScope() $this->setStore(''); } - if ($this->getScope() && $this->getScopeId() && $this->getScopeCode()) { + if ($this->getScope()) { $scope = $this->scopeResolverPool->get($this->getScope()) - ->getScope($this->getScopeId()); + ->getScope($this->getScopeCode()); if (StoreScopeInterface::SCOPE_WEBSITE === $scope->getScopeType()) { $this->setWebsite($scope->getId()); } elseif (StoreScopeInterface::SCOPE_STORE === $scope->getScopeType()) { $this->setStore($scope->getId()); } + $this->setScopeId($scope->getId()); } else { - switch (true) { - case $this->getStore(): - $scope = $this->scopeResolverPool->get(StoreScopeInterface::SCOPE_STORE) - ->getScope($this->getStore()); - break; - case $this->getWebsite(): - $scope = $this->scopeResolverPool->get(StoreScopeInterface::SCOPE_WEBSITE) - ->getScope($this->getWebsite()); - break; - default: - $scope = $this->scopeResolverPool->get(ScopeInterface::SCOPE_DEFAULT) - ->getScope(0); - break; - } + $scope = $this->resolveScope(); $this->setScope($scope->getScopeType()); $this->setScopeId($scope->getId()); $this->setScopeCode($scope->getCode()); } } + /** + * Resolve scope + * + * @return ScopeInterface + */ + private function resolveScope(): ScopeInterface + { + switch (true) { + case $this->getStore(): + $scope = $this->scopeResolverPool->get(StoreScopeInterface::SCOPE_STORE) + ->getScope($this->getStore()); + break; + case $this->getWebsite(): + $scope = $this->scopeResolverPool->get(StoreScopeInterface::SCOPE_WEBSITE) + ->getScope($this->getWebsite()); + break; + default: + $scope = $this->scopeResolverPool->get(ScopeInterface::SCOPE_DEFAULT) + ->getScope(0); + break; + } + + return $scope; + } + /** * Return formatted config data for current section * diff --git a/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/DefaultProcessorTest.php b/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/DefaultProcessorTest.php index 984e0fe842687..edb76c067bf35 100644 --- a/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/DefaultProcessorTest.php +++ b/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/DefaultProcessorTest.php @@ -7,13 +7,14 @@ use Magento\Config\App\Config\Type\System; use Magento\Config\Console\Command\ConfigSet\DefaultProcessor; +use Magento\Config\Model\Config; +use Magento\Config\Model\Config\Factory as ConfigFactory; use Magento\Framework\App\Config\ConfigPathResolver; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\DeploymentConfig; use Magento\Store\Model\ScopeInterface; use Magento\Config\Model\PreparedValueFactory; use Magento\Framework\App\Config\Value; -use Magento\Framework\App\Config\ValueInterface; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; use PHPUnit_Framework_MockObject_MockObject as Mock; @@ -55,17 +56,18 @@ class DefaultProcessorTest extends \PHPUnit\Framework\TestCase */ private $resourceModelMock; + /** + * @var ConfigFactory|Mock + */ + private $configFactory; + /** * @inheritdoc */ protected function setUp() { - $this->deploymentConfigMock = $this->getMockBuilder(DeploymentConfig::class) - ->disableOriginalConstructor() - ->getMock(); - $this->configPathResolverMock = $this->getMockBuilder(ConfigPathResolver::class) - ->disableOriginalConstructor() - ->getMock(); + $this->deploymentConfigMock = $this->createMock(DeploymentConfig::class); + $this->configPathResolverMock = $this->createMock(ConfigPathResolver::class); $this->resourceModelMock = $this->getMockBuilder(AbstractDb::class) ->disableOriginalConstructor() ->setMethods(['save']) @@ -74,14 +76,14 @@ protected function setUp() ->disableOriginalConstructor() ->setMethods(['getResource']) ->getMock(); - $this->preparedValueFactoryMock = $this->getMockBuilder(PreparedValueFactory::class) - ->disableOriginalConstructor() - ->getMock(); + $this->preparedValueFactoryMock = $this->createMock(PreparedValueFactory::class); + $this->configFactory = $this->createMock(ConfigFactory::class); $this->model = new DefaultProcessor( $this->preparedValueFactoryMock, $this->deploymentConfigMock, - $this->configPathResolverMock + $this->configPathResolverMock, + $this->configFactory ); } @@ -98,15 +100,16 @@ public function testProcess($path, $value, $scope, $scopeCode) { $this->configMockForProcessTest($path, $scope, $scopeCode); - $this->preparedValueFactoryMock->expects($this->once()) + $config = $this->createMock(Config::class); + $this->configFactory->expects($this->once()) ->method('create') - ->willReturn($this->valueMock); - $this->valueMock->expects($this->once()) - ->method('getResource') - ->willReturn($this->resourceModelMock); - $this->resourceModelMock->expects($this->once()) + ->with(['scope' => $scope, 'scope_code' => $scopeCode]) + ->willReturn($config); + $config->expects($this->once()) + ->method('setDataByPath') + ->with($path, $value); + $config->expects($this->once()) ->method('save') - ->with($this->valueMock) ->willReturnSelf(); $this->model->process($path, $value, $scope, $scopeCode); @@ -124,28 +127,6 @@ public function processDataProvider() ]; } - public function testProcessWithWrongValueInstance() - { - $path = 'test/test/test'; - $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT; - $scopeCode = null; - $value = 'value'; - $valueInterfaceMock = $this->getMockBuilder(ValueInterface::class) - ->getMockForAbstractClass(); - - $this->configMockForProcessTest($path, $scope, $scopeCode); - - $this->preparedValueFactoryMock->expects($this->once()) - ->method('create') - ->willReturn($valueInterfaceMock); - $this->valueMock->expects($this->never()) - ->method('getResource'); - $this->resourceModelMock->expects($this->never()) - ->method('save'); - - $this->model->process($path, $value, $scope, $scopeCode); - } - /** * @param string $path * @param string $scope @@ -185,6 +166,9 @@ public function testProcessLockedValue() ->method('resolve') ->willReturn('system/default/test/test/test'); + $this->configFactory->expects($this->never()) + ->method('create'); + $this->model->process($path, $value, ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null); } } From bf6487e1ec853b6f8e49074c513872cd63e4fab3 Mon Sep 17 00:00:00 2001 From: bshevchenko <1408sheva@gmail.com> Date: Fri, 21 Dec 2018 14:14:49 +0200 Subject: [PATCH 27/50] MAGETWO-96706: Cart Price Rule with related Banner for specific Customer Segment is persisted under long-term cookie --- .../Test/Mftf/ActionGroup/AdminCartPriceRuleActionGroup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCartPriceRuleActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCartPriceRuleActionGroup.xml index 33bbeff73864f..e5907e1e9c0f5 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCartPriceRuleActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCartPriceRuleActionGroup.xml @@ -35,7 +35,7 @@ <selectOption userInput="{{operatorType}}" selector="{{AdminCartPriceRulesFormSection.conditionsOperator}}" stepKey="setOperatorType"/> <click selector="{{AdminCartPriceRulesFormSection.condition('...')}}" stepKey="clickToChooseOption1"/> <fillField userInput="{{value}}" selector="{{AdminCartPriceRulesFormSection.conditionsValue}}" stepKey="fillActionValue"/> - <click selector="{{AdminCartPriceRulesFormSection.saveAndContinue}}" stepKey="clickSaveButton"/> + <click selector="{{AdminMainActionsSection.saveAndContinue}}" stepKey="clickSaveButton"/> <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> </actionGroup> </actionGroups> From 63e2850d26c0cf950e614460a3cc6b4552ba0e17 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Fri, 21 Dec 2018 19:12:44 +0200 Subject: [PATCH 28/50] MAGETWO-97247: Impossible to enable shared catalog through cli command --- app/code/Magento/Config/Model/Config.php | 85 +++++++++---------- .../Config/Test/Unit/Model/ConfigTest.php | 16 +++- 2 files changed, 53 insertions(+), 48 deletions(-) diff --git a/app/code/Magento/Config/Model/Config.php b/app/code/Magento/Config/Model/Config.php index 8aa7171bd8f72..3ec32c44324cd 100644 --- a/app/code/Magento/Config/Model/Config.php +++ b/app/code/Magento/Config/Model/Config.php @@ -12,6 +12,7 @@ use Magento\Framework\App\ScopeInterface; use Magento\Framework\App\ScopeResolverPool; use Magento\Store\Model\ScopeInterface as StoreScopeInterface; +use Magento\Store\Model\ScopeTypeNormalizer; /** * Backend config model @@ -108,6 +109,11 @@ class Config extends \Magento\Framework\DataObject */ private $scopeResolverPool; + /** + * @var ScopeTypeNormalizer + */ + private $scopeTypeNormalizer; + /** * @param \Magento\Framework\App\Config\ReinitableConfigInterface $config * @param \Magento\Framework\Event\ManagerInterface $eventManager @@ -119,6 +125,7 @@ class Config extends \Magento\Framework\DataObject * @param Config\Reader\Source\Deployed\SettingChecker|null $settingChecker * @param array $data * @param ScopeResolverPool|null $scopeResolverPool + * @param ScopeTypeNormalizer|null $scopeTypeNormalizer * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -131,7 +138,8 @@ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, SettingChecker $settingChecker = null, array $data = [], - ScopeResolverPool $scopeResolverPool = null + ScopeResolverPool $scopeResolverPool = null, + ScopeTypeNormalizer $scopeTypeNormalizer = null ) { parent::__construct($data); $this->_eventManager = $eventManager; @@ -141,8 +149,12 @@ public function __construct( $this->_configLoader = $configLoader; $this->_configValueFactory = $configValueFactory; $this->_storeManager = $storeManager; - $this->settingChecker = $settingChecker ?? ObjectManager::getInstance()->get(SettingChecker::class); - $this->scopeResolverPool = $scopeResolverPool ?? ObjectManager::getInstance()->get(ScopeResolverPool::class); + $this->settingChecker = $settingChecker + ?? ObjectManager::getInstance()->get(SettingChecker::class); + $this->scopeResolverPool = $scopeResolverPool + ?? ObjectManager::getInstance()->get(ScopeResolverPool::class); + $this->scopeTypeNormalizer = $scopeTypeNormalizer + ?? ObjectManager::getInstance()->get(ScopeTypeNormalizer::class); } /** @@ -539,53 +551,34 @@ private function initScope() if ($this->getSection() === null) { $this->setSection(''); } - if ($this->getWebsite() === null) { - $this->setWebsite(''); - } - if ($this->getStore() === null) { - $this->setStore(''); - } - if ($this->getScope()) { - $scope = $this->scopeResolverPool->get($this->getScope()) - ->getScope($this->getScopeCode()); - if (StoreScopeInterface::SCOPE_WEBSITE === $scope->getScopeType()) { - $this->setWebsite($scope->getId()); - } elseif (StoreScopeInterface::SCOPE_STORE === $scope->getScopeType()) { - $this->setStore($scope->getId()); + if (!$this->getScope()) { + switch (true) { + case $this->getStore(): + $this->setScope(StoreScopeInterface::SCOPE_STORES); + $this->setScopeCode($this->getStore()); + break; + case $this->getWebsite(): + $this->setScope(StoreScopeInterface::SCOPE_WEBSITES); + $this->setScopeCode($this->getWebsite()); + break; + default: + $this->setScope(ScopeInterface::SCOPE_DEFAULT); + $this->setScopeCode(''); + break; } - $this->setScopeId($scope->getId()); - } else { - $scope = $this->resolveScope(); - $this->setScope($scope->getScopeType()); - $this->setScopeId($scope->getId()); - $this->setScopeCode($scope->getCode()); } - } - - /** - * Resolve scope - * - * @return ScopeInterface - */ - private function resolveScope(): ScopeInterface - { - switch (true) { - case $this->getStore(): - $scope = $this->scopeResolverPool->get(StoreScopeInterface::SCOPE_STORE) - ->getScope($this->getStore()); - break; - case $this->getWebsite(): - $scope = $this->scopeResolverPool->get(StoreScopeInterface::SCOPE_WEBSITE) - ->getScope($this->getWebsite()); - break; - default: - $scope = $this->scopeResolverPool->get(ScopeInterface::SCOPE_DEFAULT) - ->getScope(0); - break; + $scope = $this->scopeResolverPool->get($this->getScope()) + ->getScope($this->getScopeCode()); + $this->setScope($this->scopeTypeNormalizer->normalize($scope->getScopeType())); + $this->setScopeCode($scope->getCode()); + $this->setScopeId($scope->getId()); + if ($this->getWebsite() === null) { + $this->setWebsite(StoreScopeInterface::SCOPE_WEBSITES === $this->getScope() ? $scope->getId() : ''); + } + if ($this->getStore() === null) { + $this->setStore(StoreScopeInterface::SCOPE_STORES === $this->getScope() ? $scope->getId() : ''); } - - return $scope; } /** diff --git a/app/code/Magento/Config/Test/Unit/Model/ConfigTest.php b/app/code/Magento/Config/Test/Unit/Model/ConfigTest.php index ab0070a3a88e7..bdcb44b756bb2 100644 --- a/app/code/Magento/Config/Test/Unit/Model/ConfigTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/ConfigTest.php @@ -77,6 +77,11 @@ class ConfigTest extends \PHPUnit\Framework\TestCase */ private $scope; + /** + * @var \Magento\Store\Model\ScopeTypeNormalizer|MockObject + */ + private $scopeTypeNormalizer; + protected function setUp() { $this->eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); @@ -118,6 +123,8 @@ protected function setUp() $this->scopeResolver->method('getScope') ->willReturn($this->scope); + $this->scopeTypeNormalizer = $this->createMock(\Magento\Store\Model\ScopeTypeNormalizer::class); + $this->model = new \Magento\Config\Model\Config( $this->appConfigMock, $this->eventManagerMock, @@ -128,7 +135,8 @@ protected function setUp() $this->storeManager, $this->settingsChecker, [], - $this->scopeResolverPool + $this->scopeResolverPool, + $this->scopeTypeNormalizer ); } @@ -284,6 +292,10 @@ public function testSaveToCheckScopeDataSet() $this->scope->expects($this->atLeastOnce()) ->method('getCode') ->willReturn('website_code'); + $this->scopeTypeNormalizer->expects($this->atLeastOnce()) + ->method('normalize') + ->with('website') + ->willReturn('websites'); $website = $this->createMock(\Magento\Store\Model\Website::class); $this->storeManager->expects($this->any())->method('getWebsites')->will($this->returnValue([$website])); $this->storeManager->expects($this->any())->method('isSingleStoreMode')->will($this->returnValue(true)); @@ -302,7 +314,7 @@ public function testSaveToCheckScopeDataSet() 'field' => 'key', 'groups' => [1 => ['fields' => ['key' => ['data']]]], 'group_id' => null, - 'scope' => 'website', + 'scope' => 'websites', 'scope_id' => 1, 'scope_code' => 'website_code', 'field_config' => null, From 7882b71c5d13804d331665cea0eba78c7abd8e66 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Mon, 24 Dec 2018 19:29:54 +0200 Subject: [PATCH 29/50] MAGETWO-97247: Impossible to enable shared catalog through cli command --- app/code/Magento/Config/Model/Config.php | 68 ++++++++++++++----- .../Config/Structure/Element/FieldPlugin.php | 2 +- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/app/code/Magento/Config/Model/Config.php b/app/code/Magento/Config/Model/Config.php index 3ec32c44324cd..b1074e92cc949 100644 --- a/app/code/Magento/Config/Model/Config.php +++ b/app/code/Magento/Config/Model/Config.php @@ -552,27 +552,11 @@ private function initScope() $this->setSection(''); } - if (!$this->getScope()) { - switch (true) { - case $this->getStore(): - $this->setScope(StoreScopeInterface::SCOPE_STORES); - $this->setScopeCode($this->getStore()); - break; - case $this->getWebsite(): - $this->setScope(StoreScopeInterface::SCOPE_WEBSITES); - $this->setScopeCode($this->getWebsite()); - break; - default: - $this->setScope(ScopeInterface::SCOPE_DEFAULT); - $this->setScopeCode(''); - break; - } - } - $scope = $this->scopeResolverPool->get($this->getScope()) - ->getScope($this->getScopeCode()); + $scope = $this->retrieveScope(); $this->setScope($this->scopeTypeNormalizer->normalize($scope->getScopeType())); $this->setScopeCode($scope->getCode()); $this->setScopeId($scope->getId()); + if ($this->getWebsite() === null) { $this->setWebsite(StoreScopeInterface::SCOPE_WEBSITES === $this->getScope() ? $scope->getId() : ''); } @@ -581,6 +565,54 @@ private function initScope() } } + /** + * Retrieve scope from initial data + * + * @return ScopeInterface + */ + private function retrieveScope(): ScopeInterface + { + $scopeType = $this->getScope(); + if (!$scopeType) { + switch (true) { + case $this->getStore(): + $scopeType = StoreScopeInterface::SCOPE_STORES; + $scopeIdentifier = $this->getStore(); + break; + case $this->getWebsite(): + $scopeType = StoreScopeInterface::SCOPE_WEBSITES; + $scopeIdentifier = $this->getWebsite(); + break; + default: + $scopeType = ScopeInterface::SCOPE_DEFAULT; + $scopeIdentifier = null; + break; + } + } else { + switch (true) { + case $this->getScopeId() !== null: + $scopeIdentifier = $this->getScopeId(); + break; + case $this->getScopeCode() !== null: + $scopeIdentifier = $this->getScopeCode(); + break; + case $this->getStore() !== null: + $scopeIdentifier = $this->getStore(); + break; + case $this->getWebsite() !== null: + $scopeIdentifier = $this->getWebsite(); + break; + default: + $scopeIdentifier = null; + break; + } + } + $scope = $this->scopeResolverPool->get($scopeType) + ->getScope($scopeIdentifier); + + return $scope; + } + /** * Return formatted config data for current section * diff --git a/app/code/Magento/Paypal/Model/Config/Structure/Element/FieldPlugin.php b/app/code/Magento/Paypal/Model/Config/Structure/Element/FieldPlugin.php index c2056aea08c00..1ba8225f3f596 100644 --- a/app/code/Magento/Paypal/Model/Config/Structure/Element/FieldPlugin.php +++ b/app/code/Magento/Paypal/Model/Config/Structure/Element/FieldPlugin.php @@ -36,7 +36,7 @@ public function __construct(RequestInterface $request) */ public function afterGetConfigPath(FieldConfigStructure $subject, $result) { - if (!$result && $this->request->getParam('section') == 'payment') { + if (!$result && strpos($subject->getPath(), 'payment_') === 0) { $result = preg_replace( '@^(' . implode('|', ConfigStructurePlugin::getPaypalConfigCountries(true)) . ')/@', 'payment/', From b89cefbc0e224ff1706accdd6f0ed9ab5016053c Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Tue, 25 Dec 2018 22:30:23 +0200 Subject: [PATCH 30/50] MAGETWO-97234: URL redirect (301) loosing current currency and displays default one --- app/code/Magento/Store/etc/frontend/di.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Store/etc/frontend/di.xml b/app/code/Magento/Store/etc/frontend/di.xml index c39d5df863939..917aedad3d960 100644 --- a/app/code/Magento/Store/etc/frontend/di.xml +++ b/app/code/Magento/Store/etc/frontend/di.xml @@ -9,7 +9,7 @@ <type name="Magento\Framework\App\FrontController"> <plugin name="requestPreprocessor" type="Magento\Store\App\FrontController\Plugin\RequestPreprocessor" sortOrder="50"/> </type> - <type name="Magento\Framework\App\Action\Action"> + <type name="Magento\Framework\App\Action\AbstractAction"> <plugin name="contextPlugin" type="Magento\Store\App\Action\Plugin\Context" sortOrder="10"/> </type> <type name="Magento\Framework\App\RouterList" shared="true"> From fd10ab514c038ea8162a4437de79f2b0d07852a6 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Tue, 25 Dec 2018 23:35:05 +0200 Subject: [PATCH 31/50] MAGETWO-97247: Impossible to enable shared catalog through cli command --- .../Config/Structure/Element/FieldPlugin.php | 14 ----------- .../Structure/Element/FieldPluginTest.php | 24 ++++--------------- 2 files changed, 5 insertions(+), 33 deletions(-) diff --git a/app/code/Magento/Paypal/Model/Config/Structure/Element/FieldPlugin.php b/app/code/Magento/Paypal/Model/Config/Structure/Element/FieldPlugin.php index 1ba8225f3f596..5d5db0128b1eb 100644 --- a/app/code/Magento/Paypal/Model/Config/Structure/Element/FieldPlugin.php +++ b/app/code/Magento/Paypal/Model/Config/Structure/Element/FieldPlugin.php @@ -5,7 +5,6 @@ */ namespace Magento\Paypal\Model\Config\Structure\Element; -use Magento\Framework\App\RequestInterface; use Magento\Config\Model\Config\Structure\Element\Field as FieldConfigStructure; use Magento\Paypal\Model\Config\StructurePlugin as ConfigStructurePlugin; @@ -14,19 +13,6 @@ */ class FieldPlugin { - /** - * @var RequestInterface - */ - private $request; - - /** - * @param RequestInterface $request - */ - public function __construct(RequestInterface $request) - { - $this->request = $request; - } - /** * Get original configPath (not changed by PayPal configuration inheritance) * diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/Element/FieldPluginTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/Element/FieldPluginTest.php index 8615b91383aaa..f0dda20b71c76 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/Element/FieldPluginTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/Element/FieldPluginTest.php @@ -7,7 +7,6 @@ use Magento\Paypal\Model\Config\Structure\Element\FieldPlugin as FieldConfigStructurePlugin; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; -use Magento\Framework\App\RequestInterface; use Magento\Config\Model\Config\Structure\Element\Field as FieldConfigStructureMock; class FieldPluginTest extends \PHPUnit\Framework\TestCase @@ -22,11 +21,6 @@ class FieldPluginTest extends \PHPUnit\Framework\TestCase */ private $objectManagerHelper; - /** - * @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $requestMock; - /** * @var FieldConfigStructureMock|\PHPUnit_Framework_MockObject_MockObject */ @@ -34,16 +28,13 @@ class FieldPluginTest extends \PHPUnit\Framework\TestCase protected function setUp() { - $this->requestMock = $this->getMockBuilder(RequestInterface::class) - ->getMockForAbstractClass(); $this->subjectMock = $this->getMockBuilder(FieldConfigStructureMock::class) ->disableOriginalConstructor() ->getMock(); $this->objectManagerHelper = new ObjectManagerHelper($this); $this->plugin = $this->objectManagerHelper->getObject( - FieldConfigStructurePlugin::class, - ['request' => $this->requestMock] + FieldConfigStructurePlugin::class ); } @@ -56,10 +47,9 @@ public function testAroundGetConfigPathHasResult() public function testAroundGetConfigPathNonPaymentSection() { - $this->requestMock->expects(static::once()) - ->method('getParam') - ->with('section') - ->willReturn('non-payment'); + $this->subjectMock->expects($this->once()) + ->method('getPath') + ->willReturn('non-payment/group/field'); $this->assertNull($this->plugin->afterGetConfigPath($this->subjectMock, null)); } @@ -72,11 +62,7 @@ public function testAroundGetConfigPathNonPaymentSection() */ public function testAroundGetConfigPath($subjectPath, $expectedConfigPath) { - $this->requestMock->expects(static::once()) - ->method('getParam') - ->with('section') - ->willReturn('payment'); - $this->subjectMock->expects(static::once()) + $this->subjectMock->expects($this->exactly(2)) ->method('getPath') ->willReturn($subjectPath); From b7721970aadcabdf7607ea5637c035f8ab45b58e Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Wed, 26 Dec 2018 14:06:57 +0200 Subject: [PATCH 32/50] MAGETWO-97247: Impossible to enable shared catalog through cli command --- .../Config/Backend/Currency/AbstractCurrency.php | 13 ++++++++----- .../Config/Console/Command/ConfigSetCommandTest.php | 7 +++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Config/Model/Config/Backend/Currency/AbstractCurrency.php b/app/code/Magento/Config/Model/Config/Backend/Currency/AbstractCurrency.php index 4ae66bfd9692b..25303093ace5d 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Currency/AbstractCurrency.php +++ b/app/code/Magento/Config/Model/Config/Backend/Currency/AbstractCurrency.php @@ -14,6 +14,8 @@ namespace Magento\Config\Model\Config\Backend\Currency; /** + * Base currency class + * * @api * @since 100.0.2 */ @@ -26,18 +28,19 @@ abstract class AbstractCurrency extends \Magento\Framework\App\Config\Value */ protected function _getAllowedCurrencies() { - if (!$this->isFormData() || $this->getData('groups/options/fields/allow/inherit')) { - return explode( + $allowValue = $this->getData('groups/options/fields/allow/value'); + $allowedCurrencies = $allowValue === null || $this->getData('groups/options/fields/allow/inherit') + ? explode( ',', (string)$this->_config->getValue( \Magento\Directory\Model\Currency::XML_PATH_CURRENCY_ALLOW, $this->getScope(), $this->getScopeId() ) - ); - } + ) + : (array) $allowValue; - return (array)$this->getData('groups/options/fields/allow/value'); + return $allowedCurrencies; } /** diff --git a/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigSetCommandTest.php b/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigSetCommandTest.php index f68f3cf37b079..73f1dd9e7b711 100644 --- a/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigSetCommandTest.php +++ b/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigSetCommandTest.php @@ -28,7 +28,7 @@ /** * Tests the different flows of config:set command. * - * {@inheritdoc} + * @inheritdoc * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @magentoDbIsolation enabled */ @@ -292,8 +292,7 @@ public function runExtendedDataProvider() * @param string $scope * @param $scopeCode string|null * @dataProvider configSetValidationErrorDataProvider - * - * @magentoDbIsolation enabled + * @magentoDbIsolation disabled */ public function testConfigSetValidationError( $path, @@ -307,6 +306,7 @@ public function testConfigSetValidationError( /** * Data provider for testConfigSetValidationError + * * @return array */ public function configSetValidationErrorDataProvider() @@ -399,7 +399,6 @@ public function testConfigSetCurrency() * Saving values with successful validation * * @dataProvider configSetValidDataProvider - * * @magentoDbIsolation enabled */ public function testConfigSetValid() From 34cb323ca88e4ee8b8b1b228c51a9a9560e8d667 Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Thu, 27 Dec 2018 12:09:08 +0200 Subject: [PATCH 33/50] MAGETWO-97350: [FT] [MFTF] StorefrontGuestCheckoutDisabledProductTest fails because of bad design --- .../Test/Mftf/ActionGroup/AdminProductGridActionGroup.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductGridActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductGridActionGroup.xml index 8d16d35ab0dde..817da18f5f2b7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductGridActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductGridActionGroup.xml @@ -243,6 +243,7 @@ <click selector="{{AdminProductGridSection.bulkActionDropdown}}" stepKey="clickActionDropdown"/> <click selector="{{AdminProductGridSection.bulkActionOption('Change status')}}" stepKey="clickChangeStatusAction"/> <click selector="{{AdminProductGridSection.changeStatus('status')}}" stepKey="clickChangeStatusDisabled" parameterized="true"/> + <waitForPageLoad stepKey="waitForStatusToBeChanged"/> <see selector="{{AdminMessagesSection.success}}" userInput="A total of 1 record(s) have been updated." stepKey="seeSuccessMessage"/> <waitForLoadingMaskToDisappear stepKey="waitForMaskToDisappear"/> <conditionalClick selector="{{AdminProductGridFilterSection.clearFilters}}" dependentSelector="{{AdminProductGridFilterSection.clearFilters}}" visible="true" stepKey="clickClearFiltersInitial2"/> From 5532227d7418d2536c55da8b84fff16c5730af1c Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 27 Dec 2018 13:01:34 +0200 Subject: [PATCH 34/50] MAGETWO-97315: [B2B] Configurable Product Price is absent on Storefront --- .../Pricing/Renderer/SalableResolver.php | 21 ++--- .../Pricing/Renderer/SalableResolverTest.php | 82 +++++++++++++++++++ 2 files changed, 91 insertions(+), 12 deletions(-) create mode 100644 app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/Catalog/Model/Product/Pricing/Renderer/SalableResolverTest.php diff --git a/app/code/Magento/ConfigurableProduct/Plugin/Catalog/Model/Product/Pricing/Renderer/SalableResolver.php b/app/code/Magento/ConfigurableProduct/Plugin/Catalog/Model/Product/Pricing/Renderer/SalableResolver.php index df8782ae422b4..c828c0929b40c 100644 --- a/app/code/Magento/ConfigurableProduct/Plugin/Catalog/Model/Product/Pricing/Renderer/SalableResolver.php +++ b/app/code/Magento/ConfigurableProduct/Plugin/Catalog/Model/Product/Pricing/Renderer/SalableResolver.php @@ -5,7 +5,7 @@ */ namespace Magento\ConfigurableProduct\Plugin\Catalog\Model\Product\Pricing\Renderer; -use Magento\ConfigurableProduct\Pricing\Price\LowestPriceOptionsProviderInterface; +use Magento\ConfigurableProduct\Model\Product\Type\Configurable as TypeConfigurable; /** * A plugin for a salable resolver. @@ -13,17 +13,16 @@ class SalableResolver { /** - * @var LowestPriceOptionsProviderInterface + * @var TypeConfigurable */ - private $lowestPriceOptionsProvider; + private $typeConfigurable; /** - * @param LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider + * @param TypeConfigurable $typeConfigurable */ - public function __construct( - LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider - ) { - $this->lowestPriceOptionsProvider = $lowestPriceOptionsProvider; + public function __construct(TypeConfigurable $typeConfigurable) + { + $this->typeConfigurable = $typeConfigurable; } /** @@ -32,9 +31,7 @@ public function __construct( * @param \Magento\Catalog\Model\Product\Pricing\Renderer\SalableResolver $subject * @param bool $result * @param \Magento\Framework\Pricing\SaleableInterface $salableItem - * * @return bool - * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function afterIsSalable( @@ -42,8 +39,8 @@ public function afterIsSalable( $result, \Magento\Framework\Pricing\SaleableInterface $salableItem ) { - if ($salableItem->getTypeId() == 'configurable' && $result) { - $result = $salableItem->isSalable(); + if ($salableItem->getTypeId() === TypeConfigurable::TYPE_CODE && $result) { + $result = $this->typeConfigurable->isSalable($salableItem); } return $result; diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/Catalog/Model/Product/Pricing/Renderer/SalableResolverTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/Catalog/Model/Product/Pricing/Renderer/SalableResolverTest.php new file mode 100644 index 0000000000000..7ec2ce370ac5d --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/Catalog/Model/Product/Pricing/Renderer/SalableResolverTest.php @@ -0,0 +1,82 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\ConfigurableProduct\Test\Unit\Plugin\Catalog\Model\Product\Pricing\Renderer; + +use Magento\Catalog\Model\Product\Pricing\Renderer\SalableResolver; +use Magento\ConfigurableProduct\Model\Product\Type\Configurable as TypeConfigurable; +use Magento\ConfigurableProduct\Plugin\Catalog\Model\Product\Pricing\Renderer\SalableResolver as SalableResolverPlugin; +use Magento\Framework\Pricing\SaleableInterface; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +class SalableResolverTest extends TestCase +{ + /** + * @var TypeConfigurable|MockObject + */ + private $typeConfigurable; + + /** + * @var SalableResolverPlugin + */ + private $salableResolver; + + protected function setUp() + { + $this->typeConfigurable = $this->createMock(TypeConfigurable::class); + $this->salableResolver = new SalableResolverPlugin($this->typeConfigurable); + } + + /** + * @param SaleableInterface|MockObject $salableItem + * @param bool $isSalable + * @param bool $typeIsSalable + * @param bool $expectedResult + * @return void + * @dataProvider afterIsSalableDataProvider + */ + public function testAfterIsSalable($salableItem, bool $isSalable, bool $typeIsSalable, bool $expectedResult): void + { + $salableResolver = $this->createMock(SalableResolver::class); + + $this->typeConfigurable->method('isSalable') + ->willReturn($typeIsSalable); + + $result = $this->salableResolver->afterIsSalable($salableResolver, $isSalable, $salableItem); + $this->assertEquals($expectedResult, $result); + } + + /** + * @return array + */ + public function afterIsSalableDataProvider(): array + { + $simpleSalableItem = $this->createMock(SaleableInterface::class); + $simpleSalableItem->expects($this->once()) + ->method('getTypeId') + ->willReturn('simple'); + + $configurableSalableItem = $this->createMock(SaleableInterface::class); + $configurableSalableItem->expects($this->once()) + ->method('getTypeId') + ->willReturn('configurable'); + + return [ + [ + $simpleSalableItem, + true, + false, + true, + ], + [ + $configurableSalableItem, + true, + false, + false, + ], + ]; + } +} From 1f3c5dc1d4b5eb6e56d40b55f5313d2efc8b721e Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 27 Dec 2018 15:38:26 +0200 Subject: [PATCH 35/50] MAGETWO-96908: [2.3] Wrong attribute value in flat table --- .../Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php index a3322b3231755..2252b3e3d5506 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php @@ -349,6 +349,7 @@ protected function _updateTemporaryTableByStoreValues( //Update not simple attributes (eg. dropdown) $columnName = $attributeCode . $valueFieldSuffix; if (isset($flatColumns[$columnName])) { + $columnValue = $this->_connection->getIfNullSql('ts.value', 't0.value'); $select = $this->_connection->select(); $select->joinLeft( ['t0' => $this->_productIndexerHelper->getTable('eav_attribute_option_value')], @@ -359,8 +360,8 @@ protected function _updateTemporaryTableByStoreValues( 'ts.option_id = et.' . $attributeCode . ' AND ts.store_id = ' . $storeId, [] )->columns( - [$columnName => $this->_connection->getIfNullSql('ts.value', 't0.value')] - )->where($columnName . ' IS NOT NULL'); + [$columnName => $columnValue] + )->where($columnValue . ' IS NOT NULL'); if (!empty($changedIds)) { $select->where($this->_connection->quoteInto('et.entity_id IN (?)', $changedIds)); } From ff5d282a209b4b97dacd57f52a4777644ff8bc82 Mon Sep 17 00:00:00 2001 From: Andrii Meysar <andrii.meysar@transoftgroup.com> Date: Thu, 27 Dec 2018 22:32:50 +0200 Subject: [PATCH 36/50] MAGETWO-97349: [FT] [MFTF] AdminFilteringCategoryProductsUsingScopeSelectorTest fails because of bad design --- .../ActionGroup/AdminProductActionGroup.xml | 1 + ...CategoryProductsUsingScopeSelectorTest.xml | 70 ++++++------------- .../Store/Test/Mftf/Data/StoreData.xml | 9 +++ .../Store/Test/Mftf/Data/StoreGroupData.xml | 16 +++++ .../Mftf/Section/AdminMainActionsSection.xml | 2 +- 5 files changed, 50 insertions(+), 48 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml index 2b5fbfbe6a79b..ae222c8454303 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml @@ -70,6 +70,7 @@ <!--Save product and see success message--> <actionGroup name="saveProductForm"> + <scrollToTopOfPage stepKey="scrollToTop"/> <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="clickSaveProduct"/> <see selector="{{AdminProductMessagesSection.successMessage}}" userInput="You saved the product." stepKey="seeSaveConfirmation"/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilteringCategoryProductsUsingScopeSelectorTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilteringCategoryProductsUsingScopeSelectorTest.xml index efceff6ffb177..e0e214342ad72 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilteringCategoryProductsUsingScopeSelectorTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilteringCategoryProductsUsingScopeSelectorTest.xml @@ -19,19 +19,19 @@ </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <!--Create website, Sore adn Store View--> - <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="adminCreateWebsite"> - <argument name="newWebsiteName" value="secondWebsite"/> - <argument name="websiteCode" value="second_website"/> + <!--Create website, Store and Store View--> + <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="createSecondWebsite"> + <argument name="newWebsiteName" value="{{secondCustomWebsite.name}}"/> + <argument name="websiteCode" value="{{secondCustomWebsite.code}}"/> </actionGroup> - <actionGroup ref="AdminCreateNewStoreGroupActionGroup" stepKey="adminCreateStore"> - <argument name="website" value="secondWebsite"/> - <argument name="storeGroupName" value="secondStore"/> - <argument name="storeGroupCode" value="second_store"/> + <actionGroup ref="AdminCreateNewStoreGroupActionGroup" stepKey="createSecondStoreGroup"> + <argument name="website" value="{{secondCustomWebsite.name}}"/> + <argument name="storeGroupName" value="{{SecondStoreGroupUnique.name}}"/> + <argument name="storeGroupCode" value="{{SecondStoreGroupUnique.code}}"/> </actionGroup> - <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="adminCreateStoreView"> - <argument name="StoreGroup" value="customStoreTierPrice"/> - <argument name="customStore" value="customStoreView"/> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createSecondStoreView"> + <argument name="StoreGroup" value="SecondStoreGroupUnique"/> + <argument name="customStore" value="SecondStoreUnique"/> </actionGroup> <!--Create Simple Product and Category --> @@ -60,9 +60,7 @@ <click selector="{{ProductInWebsitesSection.sectionHeader}}" stepKey="clickToOpenWebsiteSection"/> <waitForPageLoad stepKey="waitForToOpenedWebsiteSection"/> <uncheckOption selector="{{ProductInWebsitesSection.website('Main Website')}}" stepKey="uncheckWebsite"/> - <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="clickSaveProduct"/> - <see selector="{{AdminProductMessagesSection.successMessage}}" userInput="You saved the product." - stepKey="seeSuccessMessage"/> + <actionGroup ref="saveProductForm" stepKey="saveProduct1"/> <!-- Set filter to product name and product2 in website 2 only --> <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForProduct2"> @@ -72,12 +70,10 @@ <argument name="product" value="$$createProduct2$$"/> </actionGroup> <actionGroup ref="SelectProductInWebsitesActionGroup" stepKey="selectProductInWebsites"> - <argument name="website" value="secondWebsite"/> + <argument name="website" value="{{secondCustomWebsite.name}}"/> </actionGroup> <uncheckOption selector="{{ProductInWebsitesSection.website('Main Website')}}" stepKey="uncheckWebsite1"/> - <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="clickSaveProduct1"/> - <see selector="{{AdminProductMessagesSection.successMessage}}" userInput="You saved the product." - stepKey="seeSuccessMessage1"/> + <actionGroup ref="saveProductForm" stepKey="saveProduct2"/> <!-- Set filter to product name and product12 assigned to both websites 1 and 2 --> <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForProduct12"> @@ -87,15 +83,13 @@ <argument name="product" value="$$createProduct12$$"/> </actionGroup> <actionGroup ref="SelectProductInWebsitesActionGroup" stepKey="selectProductInWebsites1"> - <argument name="website" value="secondWebsite"/> + <argument name="website" value="{{secondCustomWebsite.name}}"/> </actionGroup> - <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="clickSaveProduct2"/> - <see selector="{{AdminProductMessagesSection.successMessage}}" userInput="You saved the product." - stepKey="seeSuccessMessage2"/> + <actionGroup ref="saveProductForm" stepKey="saveProduct3"/> </before> <after> <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite"> - <argument name="websiteName" value="secondWebsite"/> + <argument name="websiteName" value="{{secondCustomWebsite.name}}"/> </actionGroup> <actionGroup ref="ClearProductsFilterActionGroup" stepKey="clearProductsFilter"/> <deleteData createDataKey="createProduct0" stepKey="deleteProduct"/> @@ -107,7 +101,6 @@ </after> <!-- Step 1-2: Open Category page and Set scope selector to All Store Views--> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="goToCategoryPage"/> - <waitForPageLoad stepKey="waitForCategoryPageLoad"/> <click selector="{{AdminCategorySidebarTreeSection.categoryInTree($$createCategory.name$$)}}" stepKey="clickCategoryName"/> <click selector="{{AdminCategoryProductsSection.sectionHeader}}" stepKey="openProductSection"/> @@ -126,17 +119,9 @@ <!-- Step 3: Set scope selector to Website1( Storeview for the Website 1) --> <scrollToTopOfPage stepKey="scrollToTopOfPage"/> - <click selector="{{AdminCategoryMainActionsSection.CategoryStoreViewDropdownToggle}}" - stepKey="clickStoresList"/> - <waitForPageLoad stepKey="waitForCategoryPageLoad1"/> - <click selector="{{AdminCategoryMainActionsSection.CategoryStoreViewOption('Default Store View')}}" - stepKey="clickStoreView"/> - <waitForElementVisible selector="{{AdminCategoryMainActionsSection.CategoryStoreViewModalAccept}}" - stepKey="waitForPopup1"/> - <click selector="{{AdminCategoryMainActionsSection.CategoryStoreViewModalAccept}}" stepKey="clickActionAccept"/> - <waitForElementNotVisible selector="{{AdminCategoryMainActionsSection.CategoryStoreViewModalAccept}}" - stepKey="waitForNotVisibleModalAccept"/> - <waitForPageLoad stepKey="waitForCategoryPageLoad2"/> + <actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="swichToDefaultStoreView"> + <argument name="storeView" value="_defaultStore.name"/> + </actionGroup> <grabTextFrom selector="{{AdminCategorySidebarTreeSection.categoryInTree($$createCategory.name$$)}}" stepKey="grabTextFromCategory1"/> <assertRegExp expected="/\(2\)$/" expectedType="string" actual="$grabTextFromCategory1" actualType="variable" @@ -154,18 +139,9 @@ <!-- Step 4: Set scope selector to Website2 ( StoreView for Website 2) --> <scrollToTopOfPage stepKey="scrollToTopOfPage1"/> - <click selector="{{AdminCategoryMainActionsSection.CategoryStoreViewDropdownToggle}}" - stepKey="clickStoresList1"/> - <waitForPageLoad stepKey="waitForCategoryPageLoad3"/> - <click selector="{{AdminCategoryMainActionsSection.CategoryStoreViewOption('secondStoreView')}}" - stepKey="clickStoreView1"/> - <waitForElementVisible selector="{{AdminCategoryMainActionsSection.CategoryStoreViewModalAccept}}" - stepKey="waitForPopup2"/> - <click selector="{{AdminCategoryMainActionsSection.CategoryStoreViewModalAccept}}" - stepKey="clickActionAccept1"/> - <waitForElementNotVisible selector="{{AdminCategoryMainActionsSection.CategoryStoreViewModalAccept}}" - stepKey="waitForNotVisibleModalAccept1"/> - <waitForPageLoad stepKey="waitForCategoryPageLoad4"/> + <actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="swichToSecondStoreView"> + <argument name="storeView" value="SecondStoreUnique.name"/> + </actionGroup> <click selector="{{AdminCategoryProductsSection.sectionHeader}}" stepKey="openProductSection2"/> <grabTextFrom selector="{{AdminCategorySidebarTreeSection.categoryInTree($$createCategory.name$$)}}" stepKey="grabTextFromCategory2"/> diff --git a/app/code/Magento/Store/Test/Mftf/Data/StoreData.xml b/app/code/Magento/Store/Test/Mftf/Data/StoreData.xml index 9fae618020ff3..78766005f7ad9 100644 --- a/app/code/Magento/Store/Test/Mftf/Data/StoreData.xml +++ b/app/code/Magento/Store/Test/Mftf/Data/StoreData.xml @@ -65,4 +65,13 @@ <data key="name" unique="suffix">StoreView</data> <data key="code" unique="suffix">StoreViewCode</data> </entity> + <entity name="SecondStoreUnique" type="store"> + <data key="name" unique="suffix">Second Store View </data> + <data key="code" unique="suffix">second_store_view_</data> + <data key="is_active">1</data> + <data key="store_id">null</data> + <data key="store_action">add</data> + <data key="store_type">store</data> + <requiredEntity type="storeGroup">SecondStoreGroup</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/Store/Test/Mftf/Data/StoreGroupData.xml b/app/code/Magento/Store/Test/Mftf/Data/StoreGroupData.xml index e575ca3317ab6..2127b5f3c8b21 100644 --- a/app/code/Magento/Store/Test/Mftf/Data/StoreGroupData.xml +++ b/app/code/Magento/Store/Test/Mftf/Data/StoreGroupData.xml @@ -21,6 +21,22 @@ <data key="store_action">add</data> <data key="store_type">group</data> </entity> + <entity name="SecondStoreGroup" type="group"> + <data key="group_id">null</data> + <data key="name">Second Store</data> + <data key="code">second_store</data> + <var key="root_category_id" entityKey="id" entityType="category"/> + <data key="store_action">add</data> + <data key="store_type">group</data> + </entity> + <entity name="SecondStoreGroupUnique" type="group"> + <data key="group_id">null</data> + <data key="name" unique="suffix">Second Store </data> + <data key="code" unique="suffix">second_store_</data> + <var key="root_category_id" entityKey="id" entityType="category"/> + <data key="store_action">add</data> + <data key="store_type">group</data> + </entity> <entity name="staticStoreGroup" type="group"> <data key="name">NewStore</data> <data key="code" unique="suffix">Base12</data> diff --git a/app/code/Magento/Store/Test/Mftf/Section/AdminMainActionsSection.xml b/app/code/Magento/Store/Test/Mftf/Section/AdminMainActionsSection.xml index fda182246db4a..0d469a8776422 100644 --- a/app/code/Magento/Store/Test/Mftf/Section/AdminMainActionsSection.xml +++ b/app/code/Magento/Store/Test/Mftf/Section/AdminMainActionsSection.xml @@ -11,6 +11,6 @@ <section name="AdminMainActionsSection"> <element name="storeSwitcher" type="text" selector=".store-switcher"/> <element name="storeViewDropdown" type="button" selector="#store-change-button"/> - <element name="storeViewByName" type="button" selector="//*[@class='store-switcher-store-view ']/a[contains(text(), '{{storeViewName}}')]" timeout="30" parameterized="true"/> + <element name="storeViewByName" type="button" selector="//*[contains(@class,'store-switcher-store-view')]/*[contains(text(), '{{storeViewName}}')]" timeout="30" parameterized="true"/> </section> </sections> From 18cc46d5f1770b5b84b341165bfd2bcde2ec9169 Mon Sep 17 00:00:00 2001 From: dimonovp <dimonovp@gmail.com> Date: Fri, 28 Dec 2018 11:09:49 +0200 Subject: [PATCH 37/50] MAGETWO-96244: Verify that Gift Wrapping can be applied on Order Level and Ordered Items for Additional Website --- .../Mftf/Data/WebUrlOptionsConfigData.xml | 24 +++++++++++++++++++ .../Metadata/web_url_options_config-meta.xml | 22 +++++++++++++++++ .../AdminSwitchWebsiteActionGroup.xml | 21 ++++++++++++++++ .../Mftf/Section/AdminMainActionsSection.xml | 1 + 4 files changed, 68 insertions(+) create mode 100644 app/code/Magento/Config/Test/Mftf/Data/WebUrlOptionsConfigData.xml create mode 100644 app/code/Magento/Config/Test/Mftf/Metadata/web_url_options_config-meta.xml create mode 100644 app/code/Magento/Store/Test/Mftf/ActionGroup/AdminSwitchWebsiteActionGroup.xml diff --git a/app/code/Magento/Config/Test/Mftf/Data/WebUrlOptionsConfigData.xml b/app/code/Magento/Config/Test/Mftf/Data/WebUrlOptionsConfigData.xml new file mode 100644 index 0000000000000..eda0eb904be86 --- /dev/null +++ b/app/code/Magento/Config/Test/Mftf/Data/WebUrlOptionsConfigData.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="DefaultWebUrlOptionsConfig" type="web_url_use_store"> + <requiredEntity type="url_use_store_value">DefaultConfigWebUrlOptions</requiredEntity> + </entity> + <entity name="DefaultConfigWebUrlOptions" type="url_use_store_value"> + <data key="value">0</data> + </entity> + + <entity name="EnableWebUrlOptionsConfig" type="web_url_use_store"> + <requiredEntity type="url_use_store_value">WebUrlOptionsYes</requiredEntity> + </entity> + <entity name="WebUrlOptionsYes" type="url_use_store_value"> + <data key="value">1</data> + </entity> +</entities> diff --git a/app/code/Magento/Config/Test/Mftf/Metadata/web_url_options_config-meta.xml b/app/code/Magento/Config/Test/Mftf/Metadata/web_url_options_config-meta.xml new file mode 100644 index 0000000000000..fc14ba7bbaba3 --- /dev/null +++ b/app/code/Magento/Config/Test/Mftf/Metadata/web_url_options_config-meta.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataOperation.xsd"> + <operation name="WebUrlOptionsConfig" dataType="web_url_use_store" type="create" auth="adminFormKey" url="/admin/system_config/save/section/web/" + method="POST" successRegex="/messages-message-success/" returnRegex=""> + <object key="groups" dataType="web_url_use_store"> + <object key="url" dataType="web_url_use_store"> + <object key="fields" dataType="web_url_use_store"> + <object key="use_store" dataType="url_use_store_value"> + <field key="value">string</field> + </object> + </object> + </object> + </object> + </operation> +</operations> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminSwitchWebsiteActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminSwitchWebsiteActionGroup.xml new file mode 100644 index 0000000000000..cfb2c7e6347c3 --- /dev/null +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminSwitchWebsiteActionGroup.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="AdminSwitchWebsiteActionGroup"> + <arguments> + <argument name="website"/> + </arguments> + <click selector="{{AdminMainActionsSection.storeViewDropdown}}" stepKey="clickWebsiteSwitchDropdown"/> + <waitForElementVisible selector="{{AdminMainActionsSection.websiteByName('Main Website')}}" stepKey="waitForWebsiteAreVisible"/> + <click selector="{{AdminMainActionsSection.websiteByName(website.name)}}" stepKey="clickWebsiteByName"/> + <waitForElementVisible selector="{{AdminConfirmationModalSection.ok}}" stepKey="waitingForInformationModal"/> + <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="confirmStoreSwitch"/> + <see userInput="{{website.name}}" selector="{{AdminMainActionsSection.storeSwitcher}}" stepKey="seeNewWebsiteName"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Store/Test/Mftf/Section/AdminMainActionsSection.xml b/app/code/Magento/Store/Test/Mftf/Section/AdminMainActionsSection.xml index fda182246db4a..1a95d88d454e4 100644 --- a/app/code/Magento/Store/Test/Mftf/Section/AdminMainActionsSection.xml +++ b/app/code/Magento/Store/Test/Mftf/Section/AdminMainActionsSection.xml @@ -12,5 +12,6 @@ <element name="storeSwitcher" type="text" selector=".store-switcher"/> <element name="storeViewDropdown" type="button" selector="#store-change-button"/> <element name="storeViewByName" type="button" selector="//*[@class='store-switcher-store-view ']/a[contains(text(), '{{storeViewName}}')]" timeout="30" parameterized="true"/> + <element name="websiteByName" type="button" selector="//*[@class='store-switcher-website ']/a[contains(text(), '{{websiteName}}')]" timeout="30" parameterized="true"/> </section> </sections> From 48e2544228d7e7e4467ae8aa8dfe4941acf93ddb Mon Sep 17 00:00:00 2001 From: Stas Puga <stas.puga@transoftgroup.com> Date: Fri, 28 Dec 2018 15:32:47 +0200 Subject: [PATCH 38/50] MAGETWO-97030: Product image assignment for multiple stores --- .../Section/AdminSlideOutDialogSection.xml | 22 +++ .../AdminAssignImageRolesActionGroup.xml | 24 ++++ .../ActionGroup/AdminProductActionGroup.xml | 1 + .../Catalog/Test/Mftf/Data/ProductData.xml | 9 ++ .../Section/AdminProductImagesSection.xml | 3 +- .../Section/StorefrontProductMediaSection.xml | 1 + ...ctImageAssignmentForMultipleStoresTest.xml | 133 ++++++++++++++++++ .../AdminSwitchStoreViewActionGroup.xml | 4 + .../StorefrontSwitchStoreViewActionGroup.xml | 2 +- .../Store/Test/Mftf/Data/StoreData.xml | 8 +- .../Mftf/Section/AdminMainActionsSection.xml | 1 + 11 files changed, 202 insertions(+), 6 deletions(-) create mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminSlideOutDialogSection.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAssignImageRolesActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Test/AdminProductImageAssignmentForMultipleStoresTest.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminSlideOutDialogSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminSlideOutDialogSection.xml new file mode 100644 index 0000000000000..77922b8c2b5fa --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminSlideOutDialogSection.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminSlideOutDialogSection"> + <element name="closeButton" type="button" selector=".modal-slide._show [data-role='closeBtn']" timeout="30"/> + <element name="cancelButton" type="button" + selector="//*[contains(@class, 'modal-slide') and contains(@class, '_show')]//*[contains(@class, 'page-actions')]//button[normalize-space(.)='Cancel']" + timeout="30"/> + <element name="doneButton" type="button" + selector="//*[contains(@class, 'modal-slide') and contains(@class, '_show')]//*[contains(@class, 'page-actions')]//button[normalize-space(.)='Done']" + timeout="30"/> + <element name="saveButton" type="button" + selector="//*[contains(@class, 'modal-slide') and contains(@class, '_show')]//*[contains(@class, 'page-actions')]//button[normalize-space(.)='Save']" + timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAssignImageRolesActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAssignImageRolesActionGroup.xml new file mode 100644 index 0000000000000..90ceb1e4a1f96 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAssignImageRolesActionGroup.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminAssignImageRolesActionGroup"> + <arguments> + <argument name="image"/> + </arguments> + <conditionalClick selector="{{AdminProductImagesSection.productImagesToggleState('closed')}}" dependentSelector="{{AdminProductImagesSection.productImagesToggleState('open')}}" visible="false" stepKey="clickSectionImage"/> + <click selector="{{AdminProductImagesSection.imageFile(image.fileName)}}" stepKey="clickProductImage"/> + <waitForElementVisible selector="{{AdminProductImagesSection.altText}}" stepKey="seeAltTextSection"/> + <checkOption selector="{{AdminProductImagesSection.roleBase}}" stepKey="checkRoleBase"/> + <checkOption selector="{{AdminProductImagesSection.roleSmall}}" stepKey="checkRoleSmall"/> + <checkOption selector="{{AdminProductImagesSection.roleThumbnail}}" stepKey="checkRoleThumbnail"/> + <checkOption selector="{{AdminProductImagesSection.roleSwatch}}" stepKey="checkRoleSwatch"/> + <click selector="{{AdminSlideOutDialogSection.closeButton}}" stepKey="clickCloseButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml index 2b5fbfbe6a79b..28587e6405e49 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml @@ -70,6 +70,7 @@ <!--Save product and see success message--> <actionGroup name="saveProductForm"> + <scrollToTopOfPage stepKey="scrollTopPageProduct"/> <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="clickSaveProduct"/> <see selector="{{AdminProductMessagesSection.successMessage}}" userInput="You saved the product." stepKey="seeSaveConfirmation"/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 23253ad6ad8f8..74492ed416206 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -497,4 +497,13 @@ <data key="name" unique="suffix">Product With Long Name And Sku - But not too long</data> <data key="sku" unique="suffix">Product With Long Name And Sku - But not too long</data> </entity> + <entity name="Magento3" type="image"> + <data key="title" unique="suffix">Magento3</data> + <data key="price">1.00</data> + <data key="file_type">Upload File</data> + <data key="shareable">Yes</data> + <data key="file">magento3.jpg</data> + <data key="filename">magento3</data> + <data key="file_extension">jpg</data> + </entity> </entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductImagesSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductImagesSection.xml index eca0cb6f02ea1..89eb1ed678cc9 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductImagesSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductImagesSection.xml @@ -16,6 +16,7 @@ <element name="removeImageButton" type="button" selector=".action-remove"/> <element name="modalOkBtn" type="button" selector="button.action-primary.action-accept"/> <element name="uploadProgressBar" type="text" selector=".uploader .file-row"/> + <element name="productImagesToggleState" type="button" selector="[data-index='gallery'] > [data-state-collapsible='{{status}}']" parameterized="true"/> <element name="nthProductImage" type="button" selector="#media_gallery_content > div:nth-child({{var}}) img.product-image" parameterized="true"/> <element name="nthRemoveImageBtn" type="button" selector="#media_gallery_content > div:nth-child({{var}}) button.action-remove" parameterized="true"/> @@ -32,4 +33,4 @@ <element name="isThumbnailSelected" type="button" selector="//div[contains(@class, 'field-image-role')]//ul/li[contains(@class, 'selected')]/label[normalize-space(.) = 'Thumbnail']"/> <element name="isSwatchSelected" type="button" selector="//div[contains(@class, 'field-image-role')]//ul/li[contains(@class, 'selected')]/label[normalize-space(.) = 'Swatch']"/> </section> -</sections> \ No newline at end of file +</sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductMediaSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductMediaSection.xml index 83c3ca5348606..45e0b03e8d995 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductMediaSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductMediaSection.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontProductMediaSection"> <element name="imageFile" type="text" selector="//*[@class='product media']//img[contains(@src, '{{filename}}')]" parameterized="true"/> + <element name="productImageActive" type="text" selector=".product.media div[data-active=true] > img[src*='{{filename}}']" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductImageAssignmentForMultipleStoresTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductImageAssignmentForMultipleStoresTest.xml new file mode 100644 index 0000000000000..b9a5a31ad2168 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductImageAssignmentForMultipleStoresTest.xml @@ -0,0 +1,133 @@ +<?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="AdminProductImageAssignmentForMultipleStoresTest"> + <annotations> + <features value="Catalog"/> + <stories value="Product image assignment for multiple stores"/> + <title value="Product image assignment for multiple stores"/> + <description value="Product image assignment for multiple stores"/> + <severity value="MAJOR"/> + <testCaseId value="MAGETWO-58718"/> + <group value="product"/> + <group value="WYSIWYGDisabled"/> + </annotations> + <before> + <!-- Login Admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!-- Create Store View English --> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createStoreViewEn"> + <argument name="customStore" value="customStoreEN"/> + </actionGroup> + <!-- Create Store View France --> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createStoreViewFr"> + <argument name="customStore" value="customStoreFR"/> + </actionGroup> + <!-- Create Category and Simple Product --> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="_defaultProduct" stepKey="createSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + <field key="price">100</field> + </createData> + </before> + <after> + <!-- Delete Store View English --> + <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreViewEn"> + <argument name="customStore" value="customStoreEN"/> + </actionGroup> + <!-- Delete Store View France --> + <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreViewFr"> + <argument name="customStore" value="customStoreFR"/> + </actionGroup> + <!-- Clear Filter Store --> + <actionGroup ref="clearFiltersAdminDataGrid" stepKey="resetFiltersOnStorePage"/> + <!-- Delete Category and Simple Product --> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <!-- Clear Filter Product --> + <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductFilters"/> + <!-- Logout Admin --> + <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + </after> + <!-- Search Product and Open Edit --> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchProduct"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="openEditProduct"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + + <!-- Switch to the English store view --> + <actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="switchStoreViewEnglishProduct"> + <argument name="storeView" value="customStoreEN.name"/> + </actionGroup> + + <!-- Upload Image English --> + <actionGroup ref="addProductImage" stepKey="uploadImageEnglish"/> + <actionGroup ref="saveProductForm" stepKey="saveProduct1"/> + + <!-- Switch to the French store view --> + <actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="switchStoreViewFrenchProduct"> + <argument name="storeView" value="customStoreFR.name"/> + </actionGroup> + + <!-- Upload Image French --> + <actionGroup ref="addProductImage" stepKey="uploadImageFrench"> + <argument name="image" value="Magento3"/> + </actionGroup> + <actionGroup ref="AdminAssignImageRolesActionGroup" stepKey="assignImageRole1"> + <argument name="image" value="Magento3"/> + </actionGroup> + <actionGroup ref="saveProductForm" stepKey="saveProduct2"/> + + <!-- Switch to the All store view --> + <actionGroup ref="AdminSwitchToAllStoreViewActionGroup" stepKey="switchAllStoreViewProduct"/> + + <!-- Upload Image All Store View --> + <actionGroup ref="addProductImage" stepKey="uploadImageAllStoreView"> + <argument name="image" value="TestImageNew"/> + </actionGroup> + <actionGroup ref="AdminAssignImageRolesActionGroup" stepKey="assignImageRole"> + <argument name="image" value="TestImageNew"/> + </actionGroup> + + <!-- Change any product data product description --> + <click selector="{{AdminProductContentSection.sectionHeader}}" stepKey="openDescriptionDropDown"/> + <fillField selector="{{AdminProductContentSection.descriptionTextArea}}" userInput="This is the long description" stepKey="fillLongDescription"/> + <fillField selector="{{AdminProductContentSection.shortDescriptionTextArea}}" userInput="This is the short description" stepKey="fillShortDescription"/> + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + + <!-- Go to Product Page and see Default Store View--> + <amOnPage url="{{StorefrontProductPage.url($$createSimpleProduct.custom_attributes[url_key]$$)}}" stepKey="goToDefaultStorefrontProductPage"/> + <seeElement selector="{{StorefrontProductMediaSection.productImageActive(TestImageNew.filename)}}" stepKey="seeActiveImageDefault"/> + + <!-- English Switch Store View and see English Store View --> + <actionGroup ref="StorefrontSwitchStoreViewActionGroup" stepKey="switchStoreViewEnglish"> + <argument name="storeView" value="customStoreEN"/> + </actionGroup> + <click selector="{{StorefrontHeaderSection.NavigationCategoryByName($$createCategory.name$$)}}" stepKey="openCategoryPage"/> + <waitForPageLoad time="30" stepKey="waitForCategoryPage"/> + <seeElement selector="{{StorefrontCategoryProductSection.ProductImageBySrc(ProductImage.fileName)}}" stepKey="seeThumb"/> + <click selector="{{StorefrontCategoryProductSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="openProductPage"/> + <waitForPageLoad time="30" stepKey="waitForProductPage"/> + <seeElement selector="{{StorefrontProductMediaSection.productImageActive(ProductImage.filename)}}" stepKey="seeActiveImageEnglish"/> + + <!-- Switch France Store View and see France Store View --> + <actionGroup ref="StorefrontSwitchStoreViewActionGroup" stepKey="switchStoreViewFrance"> + <argument name="storeView" value="customStoreFR"/> + </actionGroup> + <click selector="{{StorefrontHeaderSection.NavigationCategoryByName($$createCategory.name$$)}}" stepKey="openCategoryPage1"/> + <waitForPageLoad time="30" stepKey="waitForCategoryPage1"/> + <seeElement selector="{{StorefrontCategoryProductSection.ProductImageBySrc(Magento3.fileName)}}" stepKey="seeThumb1"/> + <click selector="{{StorefrontCategoryProductSection.ProductTitleByName($$createSimpleProduct.name$$)}}" stepKey="openProductPage1"/> + <waitForPageLoad time="30" stepKey="waitForProductPage1"/> + <seeElement selector="{{StorefrontProductMediaSection.productImageActive(Magento3.filename)}}" stepKey="seeActiveImageFrance"/> + </test> +</tests> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminSwitchStoreViewActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminSwitchStoreViewActionGroup.xml index 860f094a48ecc..ac8e9d717fdca 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminSwitchStoreViewActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/AdminSwitchStoreViewActionGroup.xml @@ -20,4 +20,8 @@ <waitForPageLoad stepKey="waitForStoreViewSwitched"/> <see userInput="{{storeView}}" selector="{{AdminMainActionsSection.storeSwitcher}}" stepKey="seeNewStoreViewName"/> </actionGroup> + <actionGroup name="AdminSwitchToAllStoreViewActionGroup" extends="AdminSwitchStoreViewActionGroup"> + <click selector="{{AdminMainActionsSection.allStoreViews}}" stepKey="clickStoreViewByName" after="waitForStoreViewsAreVisible"/> + <see selector="{{AdminMainActionsSection.storeSwitcher}}" userInput="All Store Views" stepKey="seeNewStoreViewName" after="waitForStoreViewSwitched"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontSwitchStoreViewActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontSwitchStoreViewActionGroup.xml index cfcd25086e067..efd3a8c6b8cad 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontSwitchStoreViewActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/StorefrontSwitchStoreViewActionGroup.xml @@ -14,7 +14,7 @@ </arguments> <click selector="{{StorefrontHeaderSection.storeViewSwitcher}}" stepKey="clickStoreViewSwitcher"/> <waitForElementVisible selector="{{StorefrontHeaderSection.storeViewDropdown}}" stepKey="waitForStoreViewDropdown"/> - <click selector="{{StorefrontHeaderSection.storeViewOption(storeView.name)}}" stepKey="clickSelectStoreView"/> + <click selector="{{StorefrontHeaderSection.storeViewOption(storeView.code)}}" stepKey="clickSelectStoreView"/> <waitForPageLoad stepKey="waitForPageLoad"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Store/Test/Mftf/Data/StoreData.xml b/app/code/Magento/Store/Test/Mftf/Data/StoreData.xml index 9fae618020ff3..ab5fdf9b9903e 100644 --- a/app/code/Magento/Store/Test/Mftf/Data/StoreData.xml +++ b/app/code/Magento/Store/Test/Mftf/Data/StoreData.xml @@ -22,8 +22,8 @@ <requiredEntity type="storeGroup">customStoreGroup</requiredEntity> </entity> <entity name="customStoreEN" type="store"> - <data key="name">EN</data> - <data key="code">en</data> + <data key="name" unique="suffix">EN</data> + <data key="code" unique="suffix">en</data> <data key="is_active">1</data> <data key="store_id">null</data> <data key="store_action">add</data> @@ -31,8 +31,8 @@ <requiredEntity type="storeGroup">customStoreGroup</requiredEntity> </entity> <entity name="customStoreFR" type="store"> - <data key="name">FR</data> - <data key="code">fr</data> + <data key="name" unique="suffix">FR</data> + <data key="code" unique="suffix">fr</data> <data key="is_active">1</data> <data key="store_id">null</data> <data key="store_action">add</data> diff --git a/app/code/Magento/Store/Test/Mftf/Section/AdminMainActionsSection.xml b/app/code/Magento/Store/Test/Mftf/Section/AdminMainActionsSection.xml index fda182246db4a..211ad6f370cae 100644 --- a/app/code/Magento/Store/Test/Mftf/Section/AdminMainActionsSection.xml +++ b/app/code/Magento/Store/Test/Mftf/Section/AdminMainActionsSection.xml @@ -12,5 +12,6 @@ <element name="storeSwitcher" type="text" selector=".store-switcher"/> <element name="storeViewDropdown" type="button" selector="#store-change-button"/> <element name="storeViewByName" type="button" selector="//*[@class='store-switcher-store-view ']/a[contains(text(), '{{storeViewName}}')]" timeout="30" parameterized="true"/> + <element name="allStoreViews" type="button" selector=".store-switcher .store-switcher-all" timeout="30"/> </section> </sections> From 398ae009b12427b1b385ee3427c2a418ffa7042d Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Mon, 31 Dec 2018 13:01:39 +0200 Subject: [PATCH 39/50] MAGETWO-97210: Add Product by SKU to category causes the browser to hang --- .../UrlRewrite/Model/Storage/DbStorage.php | 72 +++++++++++-------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php b/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php index f4aa61b145f62..1b97c97ccd9a9 100644 --- a/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php +++ b/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php @@ -161,41 +161,51 @@ private function deleteOldUrls(array $urls): void $oldUrlsSelect->from( $this->resource->getTableName(self::TABLE_NAME) ); + + $uniqueEntities = $this->prepareUniqueEntities($urls); + foreach ($uniqueEntities as $storeId => $entityTypes) { + foreach ($entityTypes as $entityType => $entities) { + $oldUrlsSelect->orWhere( + $this->connection->quoteIdentifier( + UrlRewrite::STORE_ID + ) . ' = ' . $this->connection->quote($storeId, 'INTEGER') . + ' AND ' . $this->connection->quoteIdentifier( + UrlRewrite::ENTITY_ID + ) . ' IN (' . $this->connection->quote($entities, 'INTEGER') . ')' . + ' AND ' . $this->connection->quoteIdentifier( + UrlRewrite::ENTITY_TYPE + ) . ' = ' . $this->connection->quote($entityType) + ); + } + } + + $this->connection->query( + $oldUrlsSelect->deleteFromSelect( + $this->resource->getTableName(self::TABLE_NAME) + ) + ); + } + + /** + * Prepare array with unique entities + * + * @param UrlRewrite[] $urls + * @return array + */ + private function prepareUniqueEntities(array $urls): array + { + $uniqueEntities = []; /** @var UrlRewrite $url */ foreach ($urls as $url) { - $oldUrlsSelect->orWhere( - $this->connection->quoteIdentifier( - UrlRewrite::ENTITY_TYPE - ) . ' = ?', - $url->getEntityType() - ); - $oldUrlsSelect->where( - $this->connection->quoteIdentifier( - UrlRewrite::ENTITY_ID - ) . ' = ?', - $url->getEntityId() - ); - $oldUrlsSelect->where( - $this->connection->quoteIdentifier( - UrlRewrite::STORE_ID - ) . ' = ?', - $url->getStoreId() - ); - } + $entityIds = (!empty($uniqueEntities[$url->getStoreId()][$url->getEntityType()])) ? + $uniqueEntities[$url->getStoreId()][$url->getEntityType()] : []; - // prevent query locking in a case when nothing to delete - $checkOldUrlsSelect = clone $oldUrlsSelect; - $checkOldUrlsSelect->reset(Select::COLUMNS); - $checkOldUrlsSelect->columns('count(*)'); - $hasOldUrls = (bool)$this->connection->fetchOne($checkOldUrlsSelect); - - if ($hasOldUrls) { - $this->connection->query( - $oldUrlsSelect->deleteFromSelect( - $this->resource->getTableName(self::TABLE_NAME) - ) - ); + if (!\in_array($url->getEntityId(), $entityIds)) { + $entityIds[] = $url->getEntityId(); + } + $uniqueEntities[$url->getStoreId()][$url->getEntityType()] = $entityIds; } + return $uniqueEntities; } /** From 44fcc48286d36aa594feb8b48b5b9ccf90e881bd Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Mon, 31 Dec 2018 13:24:22 +0200 Subject: [PATCH 40/50] MAGETWO-97210: Add Product by SKU to category causes the browser to hang --- .../UrlRewrite/Test/Unit/Model/Storage/DbStorageTest.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/app/code/Magento/UrlRewrite/Test/Unit/Model/Storage/DbStorageTest.php b/app/code/Magento/UrlRewrite/Test/Unit/Model/Storage/DbStorageTest.php index b96a8ef637404..697ce33be0fa7 100644 --- a/app/code/Magento/UrlRewrite/Test/Unit/Model/Storage/DbStorageTest.php +++ b/app/code/Magento/UrlRewrite/Test/Unit/Model/Storage/DbStorageTest.php @@ -445,7 +445,6 @@ public function testReplace() $urlSecond = $this->createMock(\Magento\UrlRewrite\Service\V1\Data\UrlRewrite::class); // delete - $urlFirst->expects($this->any()) ->method('getEntityType') ->willReturn('product'); @@ -479,10 +478,6 @@ public function testReplace() ->with(DbStorage::TABLE_NAME) ->will($this->returnValue('table_name')); - $this->connectionMock->expects($this->any()) - ->method('query') - ->with('sql delete query'); - // insert $urlFirst->expects($this->any()) @@ -497,10 +492,6 @@ public function testReplace() ->with(DbStorage::TABLE_NAME) ->will($this->returnValue('table_name')); - $this->connectionMock->expects($this->once()) - ->method('insertMultiple') - ->with('table_name', [['row1'], ['row2']]); - $this->storage->replace([$urlFirst, $urlSecond]); } From 87d5775b26daa9aa1a95113560b22ee760e20318 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Mon, 31 Dec 2018 14:01:33 +0200 Subject: [PATCH 41/50] MAGETWO-97210: Add Product by SKU to category causes the browser to hang --- app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php b/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php index 1b97c97ccd9a9..c867d0ab35344 100644 --- a/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php +++ b/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php @@ -87,7 +87,7 @@ protected function prepareSelect(array $data) } /** - * {@inheritdoc} + * @inheritdoc */ protected function doFindAllByData(array $data) { @@ -95,7 +95,7 @@ protected function doFindAllByData(array $data) } /** - * {@inheritdoc} + * @inheritdoc */ protected function doFindOneByData(array $data) { @@ -299,7 +299,7 @@ protected function createFilterDataBasedOnUrls($urls) } /** - * {@inheritdoc} + * @inheritdoc */ public function deleteByData(array $data) { From 2aa19a51895fbcb66294aaa731ca6c07487e029d Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Wed, 2 Jan 2019 11:19:33 +0200 Subject: [PATCH 42/50] MAGETWO-97210: Add Product by SKU to category causes the browser to hang --- .../UrlRewrite/Model/Storage/DbStorage.php | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php b/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php index c867d0ab35344..ccf43e97016e1 100644 --- a/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php +++ b/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php @@ -179,11 +179,19 @@ private function deleteOldUrls(array $urls): void } } - $this->connection->query( - $oldUrlsSelect->deleteFromSelect( - $this->resource->getTableName(self::TABLE_NAME) - ) - ); + // prevent query locking in a case when nothing to delete + $checkOldUrlsSelect = clone $oldUrlsSelect; + $checkOldUrlsSelect->reset(Select::COLUMNS); + $checkOldUrlsSelect->columns('count(*)'); + $hasOldUrls = (bool)$this->connection->fetchOne($checkOldUrlsSelect); + + if ($hasOldUrls) { + $this->connection->query( + $oldUrlsSelect->deleteFromSelect( + $this->resource->getTableName(self::TABLE_NAME) + ) + ); + } } /** From fdf8c585e8cb1849c9f4b564cf492a5e525560f3 Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Wed, 2 Jan 2019 12:18:04 +0200 Subject: [PATCH 43/50] MAGETWO-97278: Incorrect use of cookies for customer --- .../Mftf/Page/StorefrontCustomerLogoutSuccessPage.xml | 11 +++++++++++ .../Magento/Persistent/Block/Header/Additional.php | 3 +-- .../Model/Plugin/PersistentCustomerContext.php | 2 ++ ...rectWelcomeMessageAfterCustomerIsLoggedOutTest.xml | 8 ++++---- .../Test/Mftf/Section/AdminCreditMemoTotalSection.xml | 1 - .../Test/Mftf/Section/AdminInvoiceItemsSection.xml | 1 - 6 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerLogoutSuccessPage.xml diff --git a/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerLogoutSuccessPage.xml b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerLogoutSuccessPage.xml new file mode 100644 index 0000000000000..9c1fc7aa8a88d --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerLogoutSuccessPage.xml @@ -0,0 +1,11 @@ +<?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="StorefrontCustomerLogoutSuccessPage" url="customer/account/logoutSuccess/" area="storefront" module="Magento_Customer"/> +</pages> diff --git a/app/code/Magento/Persistent/Block/Header/Additional.php b/app/code/Magento/Persistent/Block/Header/Additional.php index f82a0e7250bf9..2f7f5ba604f9f 100644 --- a/app/code/Magento/Persistent/Block/Header/Additional.php +++ b/app/code/Magento/Persistent/Block/Header/Additional.php @@ -103,8 +103,7 @@ public function getCustomerId(): int */ public function getConfig(): string { - return - $this->jsonSerializer->serialize( + return $this->jsonSerializer->serialize( [ 'expirationLifetime' => $this->persistentHelper->getLifeTime(), ] diff --git a/app/code/Magento/Persistent/Model/Plugin/PersistentCustomerContext.php b/app/code/Magento/Persistent/Model/Plugin/PersistentCustomerContext.php index 4ddb1040e0db6..be8998bc9be14 100644 --- a/app/code/Magento/Persistent/Model/Plugin/PersistentCustomerContext.php +++ b/app/code/Magento/Persistent/Model/Plugin/PersistentCustomerContext.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Persistent\Model\Plugin; /** diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontCorrectWelcomeMessageAfterCustomerIsLoggedOutTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontCorrectWelcomeMessageAfterCustomerIsLoggedOutTest.xml index 7fffc6c2b0d37..2b58e5c7bf62b 100644 --- a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontCorrectWelcomeMessageAfterCustomerIsLoggedOutTest.xml +++ b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontCorrectWelcomeMessageAfterCustomerIsLoggedOutTest.xml @@ -48,13 +48,13 @@ </actionGroup> <!--Check customer name and last name in welcome message--> - <seeCurrentUrlMatches regex="~/customer/account/~" stepKey="seeCustomerAccountPageUrl"/> + <seeInCurrentUrl url="{{StorefrontCustomerDashboardPage.url}}" stepKey="seeCustomerAccountPageUrl"/> <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontHeaderSection.welcomeMessage}}" stepKey="seeLoggedInCustomerWelcomeMessage"/> <!--Logout and check default welcome message--> <actionGroup ref="CustomerLogoutStorefrontByMenuItemsActionGroup" stepKey="storefrontCustomerLogout"/> - <seeCurrentUrlMatches regex="~/customer/account/logoutSuccess/~" wait="5" stepKey="seeCustomerSignOutPageUrl"/> + <seeInCurrentUrl url="{{StorefrontCustomerLogoutSuccessPage.url}}" wait="5" stepKey="seeCustomerSignOutPageUrl"/> <see userInput="Default welcome msg!" selector="{{StorefrontHeaderSection.welcomeMessage}}" stepKey="seeDefaultWelcomeMessage"/> @@ -64,14 +64,14 @@ <argument name="Customer" value="$$createCustomerForPersistent$$"/> </actionGroup> <!--Check customer name and last name in welcome message--> - <seeCurrentUrlMatches regex="~/customer/account/~" stepKey="seeCustomerAccountPageUrl1"/> + <seeInCurrentUrl url="{{StorefrontCustomerDashboardPage.url}}" stepKey="seeCustomerAccountPageUrl1"/> <see userInput="Welcome, $$createCustomerForPersistent.firstname$$ $$createCustomerForPersistent.lastname$$!" selector="{{StorefrontHeaderSection.welcomeMessage}}" stepKey="seeLoggedInCustomerWelcomeMessage1"/> <!--Logout and check persistent customer welcome message--> <actionGroup ref="CustomerLogoutStorefrontByMenuItemsActionGroup" stepKey="storefrontCustomerLogout1"/> - <seeCurrentUrlMatches regex="~/customer/account/logoutSuccess/~" wait="5" stepKey="seeCustomerSignOutPageUrl1"/> + <seeInCurrentUrl url="{{StorefrontCustomerLogoutSuccessPage.url}}" wait="5" stepKey="seeCustomerSignOutPageUrl1"/> <see userInput="Welcome, $$createCustomerForPersistent.firstname$$ $$createCustomerForPersistent.lastname$$! Not you?" selector="{{StorefrontHeaderSection.welcomeMessage}}" stepKey="seePersistentWelcomeMessage"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml index 6eb7e9e7d16df..d65074b3eb1e3 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml @@ -19,7 +19,6 @@ <element name="emailCopy" type="checkbox" selector=".order-totals-actions #send_email"/> <element name="refundStoreCredit" type="checkbox" selector=".order-totals-actions .field-refund-store-credit input[type='checkbox']"/> <element name="submitRefundOffline" type="button" selector=".order-totals-actions button[data-ui-id='order-items-submit-button']" timeout="30"/> - <element name="submitRefundOfflineEnabled" type="button" selector=".order-totals-actions button[data-ui-id='order-items-submit-button'][class='action-default scalable save submit-button primary']" timeout="30"/> <element name="creditMemoItem" type="text" selector="#sales_order_view_tabs_order_creditmemos"/> <element name="viewMemo" type="text" selector="div#sales_order_view_tabs_order_creditmemos_content a.action-menu-item"/> </section> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceItemsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceItemsSection.xml index 03087d8949c2f..92c01cf380746 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceItemsSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceItemsSection.xml @@ -28,6 +28,5 @@ <element name="discountAmountColumn" type="text" selector=".order-invoice-tables .col-discount .price"/> <element name="totalColumn" type="text" selector=".order-invoice-tables .col-total .price"/> <element name="updateQty" type="button" selector=".order-invoice-tables tfoot button[data-ui-id='order-items-update-button']"/> - <element name="updateQtyEnabled" type="button" selector=".order-invoice-tables tfoot button[data-ui-id='order-items-update-button'][class='action-default scalable update-button']"/> </section> </sections> From 81393b8b0f4aa694be6456ac1caa8e3988bbc8e7 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Wed, 2 Jan 2019 12:44:26 +0200 Subject: [PATCH 44/50] MAGETWO-97210: Add Product by SKU to category causes the browser to hang --- app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php b/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php index ccf43e97016e1..d8ceb16d71fdc 100644 --- a/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php +++ b/app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php @@ -183,9 +183,9 @@ private function deleteOldUrls(array $urls): void $checkOldUrlsSelect = clone $oldUrlsSelect; $checkOldUrlsSelect->reset(Select::COLUMNS); $checkOldUrlsSelect->columns('count(*)'); - $hasOldUrls = (bool)$this->connection->fetchOne($checkOldUrlsSelect); + $hasOldUrls = (bool)$this->connection->fetchOne($checkOldUrlsSelect); - if ($hasOldUrls) { + if ($hasOldUrls) { $this->connection->query( $oldUrlsSelect->deleteFromSelect( $this->resource->getTableName(self::TABLE_NAME) From 14bc5920d1aeb70a807c6ee2ff26c6dfb0ef14c5 Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Wed, 2 Jan 2019 13:57:51 +0200 Subject: [PATCH 45/50] MAGETWO-97278: Incorrect use of cookies for customer --- app/code/Magento/Persistent/Block/Header/Additional.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Persistent/Block/Header/Additional.php b/app/code/Magento/Persistent/Block/Header/Additional.php index 2f7f5ba604f9f..dfde2adf1e6ab 100644 --- a/app/code/Magento/Persistent/Block/Header/Additional.php +++ b/app/code/Magento/Persistent/Block/Header/Additional.php @@ -104,9 +104,9 @@ public function getCustomerId(): int public function getConfig(): string { return $this->jsonSerializer->serialize( - [ - 'expirationLifetime' => $this->persistentHelper->getLifeTime(), - ] - ); + [ + 'expirationLifetime' => $this->persistentHelper->getLifeTime(), + ] + ); } } From 4f402c255ed0cab4d3b22015db3776ac424cff79 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 2 Jan 2019 15:06:06 +0200 Subject: [PATCH 46/50] MAGETWO-65408: [FT] Magento\Search\Test\TestCase\AdvancedSearchWithAttributeTest fails on Jenkins --- .../Magento/GroupedProduct/Test/Fixture/GroupedProduct.xml | 4 ++-- .../Search/Test/TestCase/AdvancedSearchWithAttributeTest.xml | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/GroupedProduct.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/GroupedProduct.xml index dce1358a1ecf4..59c00683e3b1a 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/GroupedProduct.xml +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/GroupedProduct.xml @@ -58,7 +58,7 @@ <field name="sku" is_required="1" group="product-details" /> <field name="small_image" is_required="0" /> <field name="small_image_label" is_required="0" /> - <field name="status" is_required="0" /> + <field name="status" is_required="0" group="product-details" /> <field name="thumbnail" is_required="0" /> <field name="thumbnail_label" is_required="0" /> <field name="updated_at" is_required="1" /> @@ -66,7 +66,7 @@ <field name="upsell_tgtr_position_limit" is_required="0" /> <field name="url_key" is_required="0" group="search-engine-optimization" /> <field name="url_path" is_required="0" /> - <field name="visibility" is_required="0" /> + <field name="visibility" is_required="0" group="product-details" /> <field name="id" /> <field name="type_id" /> <field name="attribute_set_id" group="product-details" source="Magento\Catalog\Test\Fixture\Product\AttributeSetId" /> diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/AdvancedSearchWithAttributeTest.xml b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/AdvancedSearchWithAttributeTest.xml index 13c7051d0c1ba..733b110ec5494 100644 --- a/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/AdvancedSearchWithAttributeTest.xml +++ b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/AdvancedSearchWithAttributeTest.xml @@ -8,8 +8,6 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Search\Test\TestCase\AdvancedSearchWithAttributeTest" summary="Use Advanced Search by Decimal indexable attribute if Edit/Add Attribute" ticketId="MAGETWO-25931"> <variation name="AdvancedSearchWithWeightAttributeTestVariation1"> - <data name="issue" xsi:type="string">MAGETWO-65408: [FT] Magento\Search\Test\TestCase\AdvancedSearchWithAttributeTest fails on Jenkins</data> - <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="productDropDownList/0" xsi:type="string">configurable</data> <data name="productDropDownList/1" xsi:type="string">simple</data> <data name="productDropDownList/2" xsi:type="string">bundle</data> From 107cad68b14e20aebabc0103f5643991c6e8f7f2 Mon Sep 17 00:00:00 2001 From: Stas Puga <stas.puga@transoftgroup.com> Date: Wed, 2 Jan 2019 15:07:12 +0200 Subject: [PATCH 47/50] MAGETWO-97030: Product image assignment for multiple stores --- ...tPurchaseProductWithCustomOptionsTest.xml} | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) rename app/code/Magento/Catalog/Test/Mftf/Test/{StorefrontPurchaseProductWithCustomOptions.xml => StorefrontPurchaseProductWithCustomOptionsTest.xml} (93%) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptions.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml similarity index 93% rename from app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptions.xml rename to app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml index c845a27773170..951afa2ddb68b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptions.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml @@ -8,7 +8,7 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="StorefrontPurchaseProductWithCustomOptions"> + <test name="StorefrontPurchaseProductWithCustomOptionsTest"> <annotations> <features value="Catalog"/> <stories value="Purchase a product with Custom Options of different types"/> @@ -53,6 +53,10 @@ <seeElement selector="{{StorefrontProductInfoMainSection.productAttributeOptionsMultiselect(ProductOptionMultiSelect.title, ProductOptionValueMultiSelect1.price)}}" stepKey="checkMultiSelectProductOption"/> <seeElement selector="{{StorefrontProductInfoMainSection.productAttributeOptionsData(ProductOptionDate.title, ProductOptionDate.price)}}" stepKey="checkDataProductOption"/> + <!--Generate year--> + <generateDate date="Now" format="Y" stepKey="year"/> + <generateDate date="Now" format="y" stepKey="shortYear"/> + <!-- Adding items to the checkout --> <fillField userInput="OptionField" selector="{{StorefrontProductInfoMainSection.productOptionFieldInput(ProductOptionField.title)}}" stepKey="fillProductOptionInputField"/> @@ -64,10 +68,10 @@ <selectOption userInput="{{ProductOptionValueMultiSelect1.price}}" selector="{{StorefrontProductInfoMainSection.productOptionSelect(ProductOptionMultiSelect.title)}}" stepKey="selectProductOptionMultiSelect"/> <selectOption userInput="01" selector="{{StorefrontProductInfoMainSection.productOptionDataMonth(ProductOptionDate.title)}}" stepKey="selectProductOptionDate"/> <selectOption userInput="01" selector="{{StorefrontProductInfoMainSection.productOptionDataDay(ProductOptionDate.title)}}" stepKey="selectProductOptionDate1"/> - <selectOption userInput="2018" selector="{{StorefrontProductInfoMainSection.productOptionDataYear(ProductOptionDate.title)}}" stepKey="selectProductOptionDate2"/> + <selectOption userInput="$year" selector="{{StorefrontProductInfoMainSection.productOptionDataYear(ProductOptionDate.title)}}" stepKey="selectProductOptionDate2"/> <selectOption userInput="01" selector="{{StorefrontProductInfoMainSection.productOptionDateAndTimeMonth(ProductOptionDateTime.title)}}" stepKey="selectProductOptionDateAndTimeMonth"/> <selectOption userInput="01" selector="{{StorefrontProductInfoMainSection.productOptionDateAndTimeDay(ProductOptionDateTime.title)}}" stepKey="selectProductOptionDateAndTimeDay"/> - <selectOption userInput="2018" selector="{{StorefrontProductInfoMainSection.productOptionDateAndTimeYear(ProductOptionDateTime.title)}}" stepKey="selectProductOptionDateAndTimeYear"/> + <selectOption userInput="$year" selector="{{StorefrontProductInfoMainSection.productOptionDateAndTimeYear(ProductOptionDateTime.title)}}" stepKey="selectProductOptionDateAndTimeYear"/> <selectOption userInput="01" selector="{{StorefrontProductInfoMainSection.productOptionDateAndTimeHour(ProductOptionDateTime.title)}}" stepKey="selectProductOptionDateAndTimeHour"/> <selectOption userInput="00" selector="{{StorefrontProductInfoMainSection.productOptionDateAndTimeMinute(ProductOptionDateTime.title)}}" stepKey="selectProductOptionDateAndTimeMinute"/> <selectOption userInput="01" selector="{{StorefrontProductInfoMainSection.productOptionTimeHour(ProductOptionTime.title)}}" stepKey="selectProductOptionTimeHour"/> @@ -100,8 +104,8 @@ <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($createProduct.name$)}}" userInput="{{ProductOptionValueRadioButtons1.title}}" stepKey="seeProductOptionValueRadioButtons1Input1"/> <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($createProduct.name$)}}" userInput="{{ProductOptionValueCheckbox.title}}" stepKey="seeProductOptionValueCheckboxInput1" /> <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($createProduct.name$)}}" userInput="{{ProductOptionValueMultiSelect1.title}}" stepKey="seeproductAttributeOptionsMultiselect1Input1" /> - <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($createProduct.name$)}}" userInput="Jan 1, 2018" stepKey="seeProductOptionDateAndTimeInput" /> - <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($createProduct.name$)}}" userInput="1/1/18, 1:00 AM" stepKey="seeProductOptionDataInput" /> + <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($createProduct.name$)}}" userInput="Jan 1, $year" stepKey="seeProductOptionDateAndTimeInput" /> + <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($createProduct.name$)}}" userInput="1/1/$shortYear, 1:00 AM" stepKey="seeProductOptionDataInput" /> <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($createProduct.name$)}}" userInput="1:00 AM" stepKey="seeProductOptionTimeInput" /> <!--Select shipping method--> <actionGroup ref="CheckoutSelectFlatRateShippingMethodActionGroup" stepKey="selectFlatRateShippingMethod"/> @@ -138,8 +142,8 @@ <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueRadioButtons1.title}}" stepKey="seeAdminOrderProductOptionValueRadioButton1"/> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueCheckbox.title}}" stepKey="seeAdminOrderProductOptionValueCheckbox" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueMultiSelect1.title}}" stepKey="seeAdminOrderproductAttributeOptionsMultiselect1" /> - <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="Jan 1, 2018" stepKey="seeAdminOrderProductOptionDateAndTime" /> - <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1/1/18, 1:00 AM" stepKey="seeAdminOrderProductOptionData" /> + <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="Jan 1, $year" stepKey="seeAdminOrderProductOptionDateAndTime" /> + <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1/1/$shortYear, 1:00 AM" stepKey="seeAdminOrderProductOptionData" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1:00 AM" stepKey="seeAdminOrderProductOptionTime" /> <!-- Reorder and Checking the correctness of displayed custom options for user parameters on Order and correctness of displayed price Subtotal--> @@ -156,8 +160,8 @@ <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueRadioButtons1.title}}" stepKey="seeAdminOrderProductOptionValueRadioButton11"/> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueCheckbox.title}}" stepKey="seeAdminOrderProductOptionValueCheckbox1" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueMultiSelect1.title}}" stepKey="seeAdminOrderproductAttributeOptionsMultiselect11" /> - <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="Jan 1, 2018" stepKey="seeAdminOrderProductOptionDateAndTime1" /> - <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1/1/18, 1:00 AM" stepKey="seeAdminOrderProductOptionData1" /> + <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="Jan 1, $year" stepKey="seeAdminOrderProductOptionDateAndTime1" /> + <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1/1/$shortYear, 1:00 AM" stepKey="seeAdminOrderProductOptionData1" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1:00 AM" stepKey="seeAdminOrderProductOptionTime1" /> <see selector="{{AdminOrderTotalSection.subTotal}}" userInput="{$finalProductPrice}" stepKey="seeOrderSubTotal"/> @@ -174,8 +178,8 @@ <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($createProduct.name$, ProductOptionRadiobutton.title, ProductOptionValueRadioButtons1.title)}}" userInput="{{ProductOptionValueRadioButtons1.title}}" stepKey="seeStorefontOrderProductOptionValueRadioButtons11"/> <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($createProduct.name$, ProductOptionCheckbox.title, ProductOptionValueCheckbox.title)}}" userInput="{{ProductOptionValueCheckbox.title}}" stepKey="seeStorefontOrderProductOptionValueCheckbox1" /> <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($createProduct.name$, ProductOptionMultiSelect.title, ProductOptionValueMultiSelect1.title)}}" userInput="{{ProductOptionValueMultiSelect1.title}}" stepKey="seeStorefontOrderproductAttributeOptionsMultiselect11" /> - <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($createProduct.name$, ProductOptionDate.title, 'Jan 1, 2018')}}" userInput="Jan 1, 2018" stepKey="seeStorefontOrderProductOptionDateAndTime1" /> - <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($createProduct.name$, ProductOptionDateTime.title, '1/1/18, 1:00 AM')}}" userInput="1/1/18, 1:00 AM" stepKey="seeStorefontOrderProductOptionData1" /> + <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($createProduct.name$, ProductOptionDate.title, 'Jan 1, $year')}}" userInput="Jan 1, $year" stepKey="seeStorefontOrderProductOptionDateAndTime1" /> + <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($createProduct.name$, ProductOptionDateTime.title, '1/1/$shortYear, 1:00 AM')}}" userInput="1/1/$shortYear, 1:00 AM" stepKey="seeStorefontOrderProductOptionData1" /> <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($createProduct.name$, ProductOptionTime.title, '1:00 AM')}}" userInput="1:00 AM" stepKey="seeStorefontOrderProductOptionTime1" /> <!-- Delete product and category --> From 52ff75be4310f2d60cf86d0e6be3c7f4f44758e0 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Fri, 4 Jan 2019 15:39:06 -0600 Subject: [PATCH 48/50] MC-10822: Update GB country name in USPS API --- app/code/Magento/Usps/Model/Carrier.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Usps/Model/Carrier.php b/app/code/Magento/Usps/Model/Carrier.php index 1e8faf3cc9614..afe34cac575ac 100644 --- a/app/code/Magento/Usps/Model/Carrier.php +++ b/app/code/Magento/Usps/Model/Carrier.php @@ -1246,7 +1246,7 @@ protected function _getCountryName($countryId) 'FO' => 'Faroe Islands', 'FR' => 'France', 'GA' => 'Gabon', - 'GB' => 'Great Britain and Northern Ireland', + 'GB' => 'United Kingdom of Great Britain and Northern Ireland', 'GD' => 'Grenada', 'GE' => 'Georgia, Republic of', 'GF' => 'French Guiana', @@ -1364,7 +1364,7 @@ protected function _getCountryName($countryId) 'ST' => 'Sao Tome and Principe', 'SV' => 'El Salvador', 'SY' => 'Syrian Arab Republic', - 'SZ' => 'Swaziland', + 'SZ' => 'Eswatini', 'TC' => 'Turks and Caicos Islands', 'TD' => 'Chad', 'TG' => 'Togo', From cb005564594a540c85addf6d4aa3701994376a96 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Tue, 8 Jan 2019 12:39:32 +0200 Subject: [PATCH 49/50] MAGETWO-96440: Import - Amount is not specified --- .../Magento/CatalogImportExport/Model/Export/Product.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php index 345d323e6e129..c047e9c9bef21 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php @@ -1158,7 +1158,7 @@ protected function collectMultiselectValues($item, $attrCode, $storeId) } /** - * Check attribute is valid + * Check attribute is valid. * * @param string $code * @param mixed $value @@ -1175,6 +1175,10 @@ protected function isValidAttributeValue($code, $value) $isValid = false; } + if (is_array($value)) { + $isValid = false; + } + return $isValid; } From 2ca887df5555ea9d293e45b52204634f689b38d5 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 9 Jan 2019 12:45:28 +0200 Subject: [PATCH 50/50] MAGETWO-97514: [FT] [MFTF] AdminDeleteTaxRuleTest fails because of bad design --- .../Test/Mftf/ActionGroup/FillShippingZipFormActionGroup.xml | 2 ++ app/code/Magento/Tax/Test/Mftf/Test/AdminDeleteTaxRuleTest.xml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillShippingZipFormActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillShippingZipFormActionGroup.xml index 83f6b635bfee7..f12bf4344ab12 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillShippingZipFormActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillShippingZipFormActionGroup.xml @@ -13,6 +13,8 @@ <argument name="address"/> </arguments> <conditionalClick stepKey="openShippingDetails" selector="{{CheckoutCartSummarySection.shippingHeading}}" dependentSelector="{{CheckoutCartSummarySection.country}}" visible="false"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.country}}" time="30" stepKey="waitForCountryFieldAppears"/> <selectOption stepKey="selectCountry" selector="{{CheckoutCartSummarySection.country}}" userInput="{{address.country}}"/> <selectOption stepKey="selectStateProvince" selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="{{address.state}}"/> <fillField stepKey="fillPostCode" selector="{{CheckoutCartSummarySection.postcode}}" userInput="{{address.postcode}}"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminDeleteTaxRuleTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminDeleteTaxRuleTest.xml index 658f524a4a5db..72adf7b0dae1e 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminDeleteTaxRuleTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminDeleteTaxRuleTest.xml @@ -68,7 +68,9 @@ <argument name="address" value="US_Address_Utah" /> </actionGroup> <scrollTo selector="{{StorefrontProductPageSection.orderTotal}}" x="0" y="-80" stepKey="scrollToOrderTotal"/> + <waitForElementVisible selector="{{StorefrontProductPageSection.subTotal}}" time="30" stepKey="waitSubtotalAppears"/> <see selector="{{StorefrontProductPageSection.subTotal}}" userInput="$100.00" stepKey="seeSubTotal"/> + <waitForElementVisible selector="{{StorefrontProductPageSection.shipping}}" time="30" stepKey="waitShippingAppears"/> <see selector="{{StorefrontProductPageSection.shipping}}" userInput="$5.00" stepKey="seeShipping"/> <dontSee selector="{{StorefrontProductPageSection.tax}}" stepKey="dontSeeAssertTaxAmount" /> <see selector="{{StorefrontProductPageSection.orderTotal}}" userInput="$105.00" stepKey="seeAssertOrderTotal"/>