diff --git a/app/code/Magento/Bundle/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Bundle/Test/Mftf/Data/ProductData.xml index 5034c72b9ee3f..6e7e4a7a16573 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Data/ProductData.xml @@ -107,4 +107,35 @@ CustomAttributeDynamicPrice CustomAttributePriceViewRange + + Test 123 Dynamic + test-dynamic-bundle-product + bundle + 4 + 4 + 1 + test-dynamic-bundle-product + EavStockItem + CustomDynamicProductDescription + CustomDynamicProductShortDescription + CustomAttributeDynamicPrice + CustomAttributePriceViewRange + + + Test 123 Fixed + test-fixed-bundle-product + bundle + 4 + 10 + 4 + 1 + api-fixed-bundle-product + EavStockItem + CustomFixedProductDescription + CustomFixedProductShortDescription + CustomAttributePriceView + CustomAttributeFixPrice + CustomAttributeFixWeight + CustomAttributeFixSku + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminShouldBeAbleToMassUpdateAttributesForBundleProductsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminShouldBeAbleToMassUpdateAttributesForBundleProductsTest.xml new file mode 100644 index 0000000000000..fe55fda4d0e05 --- /dev/null +++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminShouldBeAbleToMassUpdateAttributesForBundleProductsTest.xml @@ -0,0 +1,76 @@ + + + + + + + + + + <description value="Admin should be able to mass update attributes for bundle products"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-219"/> + <group value="bundle"/> + <group value="WYSIWYGDisabled"/> + </annotations> + <before> + <!-- Create Simple Product --> + <createData entity="SimpleProduct2" stepKey="createSimpleProduct"/> + <!-- Create Fixed Bundle Product --> + <createData entity="ApiFixedBundleProduct" stepKey="createFixedBundleProduct"/> + <!-- Create DropDown Bundle Option --> + <createData entity="DropDownBundleOption" stepKey="createBundleOption"> + <requiredEntity createDataKey="createFixedBundleProduct"/> + </createData> + <!-- Link Simple Product --> + <createData entity="ApiBundleLink" stepKey="createNewBundleLink"> + <requiredEntity createDataKey="createFixedBundleProduct"/> + <requiredEntity createDataKey="createBundleOption"/> + <requiredEntity createDataKey="createSimpleProduct"/> + </createData> + </before> + <after> + <!-- Delete Simple Product --> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <!-- Delete Fixed Bundle Product --> + <deleteData createDataKey="createFixedBundleProduct" stepKey="deleteBundleProduct"/> + <!-- Clear Filter --> + <actionGroup ref="ClearProductsFilterActionGroup" stepKey="clearProductFilter"/> + <!--Log Out Admin--> + <actionGroup ref="logout" stepKey="logoutAsAdmin"/> + </after> + <!-- Login as Admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!-- Go to Catalog -> Catalog -> Products and Search created product in precondition and choose it --> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchProduct"> + <argument name="product" value="$$createFixedBundleProduct$$"/> + </actionGroup> + <!-- Choose "Update attributes" and Change any product data --> + <actionGroup ref="AdminUpdateProductNameAndDescriptionAttributes" stepKey="updateProductAttribute"> + <argument name="product" value="UpdateAttributeNameAndDescription"/> + </actionGroup> + <!--Run cron twice--> + <magentoCLI command="cron:run" stepKey="cronRun"/> + <magentoCLI command="cron:run" stepKey="cronRunTwice"/> + <!-- Search for a product with a new name and Open Product --> + <actionGroup ref="filterProductGridByName" stepKey="searchWithNewProductName"> + <argument name="product" value="UpdateAttributeNameAndDescription"/> + </actionGroup> + <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="openProductPage"> + <argument name="product" value="$$createFixedBundleProduct$$"/> + </actionGroup> + <!-- Assert product name and description --> + <actionGroup ref="AssertProductNameInProductEditForm" stepKey="assertProductName"> + <argument name="productName" value="{{UpdateAttributeNameAndDescription.name}}"/> + </actionGroup> + <actionGroup ref="AssertProductDescriptionInProductEditForm" stepKey="assertProductDescription"> + <argument name="productDescription" value="{{UpdateAttributeNameAndDescription.description}}"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSearchBundleProductsByKeywordsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSearchBundleProductsByKeywordsTest.xml new file mode 100644 index 0000000000000..d27cd0df88239 --- /dev/null +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSearchBundleProductsByKeywordsTest.xml @@ -0,0 +1,137 @@ +<?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="StorefrontCustomerSearchBundleProductsByKeywordsTest"> + <annotations> + <features value="Bundle"/> + <stories value="Bundle products list on Storefront"/> + <title value="Customer should be able to see search results when searching for bundle products by keyword"/> + <description value="Customer should be able to see search results when searching for bundle products by keyword"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-227"/> + <group value="bundle"/> + </annotations> + <before> + <createData entity="SimpleProductNotVisibleIndividually" stepKey="createSimpleProduct"/> + <createData entity="DynamicBundleProductCustomDescription" stepKey="createDynamicBundle"/> + <createData entity="DropDownBundleOption" stepKey="dynamicBundleOption"> + <requiredEntity createDataKey="createDynamicBundle"/> + </createData> + <createData entity="ApiBundleLink" stepKey="createDynamicBundleLink"> + <requiredEntity createDataKey="createDynamicBundle"/> + <requiredEntity createDataKey="dynamicBundleOption"/> + <requiredEntity createDataKey="createSimpleProduct"/> + </createData> + <createData entity="SimpleProductNotVisibleIndividually" stepKey="createSimpleProductTwo"/> + <createData entity="FixedBundleProductCustomDescription" stepKey="createFixedBundle"/> + <createData entity="DropDownBundleOption" stepKey="fixedBundleOption"> + <requiredEntity createDataKey="createFixedBundle"/> + </createData> + <createData entity="ApiBundleLink" stepKey="createFixedBundleLink"> + <requiredEntity createDataKey="createFixedBundle"/> + <requiredEntity createDataKey="fixedBundleOption"/> + <requiredEntity createDataKey="createSimpleProductTwo"/> + </createData> + <magentoCLI command="indexer:reindex" arguments="cataloginventory_stock catalogsearch_fulltext" stepKey="reindex"/> + </before> + <after> + <deleteData createDataKey="createDynamicBundle" stepKey="deleteDynamicBundleProduct"/> + <deleteData createDataKey="createFixedBundle" stepKey="deleteFixedBundleProduct"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="createSimpleProductTwo" stepKey="createSimpleProductTwo"/> + </after> + <!-- 1. Go to storefront home page --> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefrontPage"/> + <!-- 2. Fill quick search bar with test values unique for dynamic bundle product and click search --> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchDynamic"> + <argument name="phrase" value="Dynamic"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="assertDynamicBundleInSearchResultByDynamic"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGrid" stepKey="assertFixedBundleInSearchResultByDynamic"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByDescription"> + <argument name="phrase" value="Dynamicscription"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="assertDynamicBundleInSearchResultByDescription"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGrid" stepKey="dontSeeFixedBundleInSearchResultByDescription"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchShortDescription"> + <argument name="phrase" value="Dynamictest"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="assertDynamicBundleInSearchResultByShortDescription"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGrid" stepKey="dontSeeFixedBundleInSearchResultByShortDescription"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <!-- 3. Fill quick search bar with test values mutual for both products and click search --> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchTest123"> + <argument name="phrase" value="Test 123"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeDynamicBundleByTest123"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeFixedBundleByTest123"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchTesting321"> + <argument name="phrase" value="Testing 321"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeDynamicBundleByTesting321"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeFixedBundleByTesting321"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchShort555"> + <argument name="phrase" value="Short 555"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeDynamicBundleByShort555"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeFixedBundleByShort555"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <!-- 4. Fill quick search bar with test values unique for fixed bundle product and click search --> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByFixed"> + <argument name="phrase" value="Fixed"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeFixedBundleByFixed"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGrid" stepKey="dontSeeDynamicBundleByFixed"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByDescriptionForFixed"> + <argument name="phrase" value="Fixedscription"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeFixedBundleByDescriptionForFixed"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGrid" stepKey="dontSeeDynamicProductByDescriptionForFixed"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByShortDescriptionForFixed"> + <argument name="phrase" value="Fixedtest"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeFixedBundleByShortDescriptionForFixed"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGrid" stepKey="dontSeeDynamicBundleByShortDescriptionForFixed"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml index 6c448d0cbbd3b..0fad3e14f6c86 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml @@ -557,4 +557,23 @@ <remove keyForRemoval="seeCheckboxForWebsite"/> <dontSeeCheckboxIsChecked selector="{{ProductInWebsitesSection.website(website)}}" after="expandProductWebsitesSection" stepKey="seeCustomWebsiteIsNotChecked"/> </actionGroup> + + <!-- You are on product Edit Page --> + <!-- Assert Product Name in admin Product page --> + <actionGroup name="AssertProductNameInProductEditForm"> + <arguments> + <argument name="productName" type="string"/> + </arguments> + <seeInField selector="{{AdminProductFormSection.productName}}" userInput="{{productName}}" stepKey="seeProductNameOnEditProductPage"/> + </actionGroup> + + <!-- You are on product Edit Page --> + <!-- Assert Product Description in admin Product page --> + <actionGroup name="AssertProductDescriptionInProductEditForm"> + <arguments> + <argument name="productDescription" type="string"/> + </arguments> + <conditionalClick selector="{{AdminProductContentSection.sectionHeader}}" dependentSelector="{{AdminProductContentSection.sectionHeaderShow}}" visible="false" stepKey="expandContentSection"/> + <seeInField selector="{{AdminProductContentSection.descriptionTextArea}}" userInput="{{productDescription}}" stepKey="seeProductDescription"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeMassUpdateActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeMassUpdateActionGroup.xml new file mode 100644 index 0000000000000..57b180ada1536 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeMassUpdateActionGroup.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Update Product Name and Description attribute --> + <actionGroup name="AdminUpdateProductNameAndDescriptionAttributes"> + <arguments> + <argument name="product"/> + </arguments> + <click selector="{{AdminProductGridSection.productGridCheckboxOnRow('1')}}" stepKey="clickCheckbox"/> + <click selector="{{AdminProductGridSection.bulkActionDropdown}}" stepKey="clickDropdown"/> + <click selector="{{AdminProductGridSection.bulkActionOption('Update attributes')}}" stepKey="clickOption"/> + <waitForPageLoad stepKey="waitForUploadPage"/> + <seeInCurrentUrl url="{{ProductAttributesEditPage.url}}" stepKey="seeAttributePageEditUrl"/> + <click selector="{{AdminUpdateAttributesSection.toggleName}}" stepKey="clickToChangeName"/> + <fillField selector="{{AdminUpdateAttributesSection.name}}" userInput="{{product.name}}" stepKey="fillFieldName"/> + <click selector="{{AdminUpdateAttributesSection.toggleDescription}}" stepKey="clickToChangeDescription"/> + <fillField selector="{{AdminUpdateAttributesSection.description}}" userInput="{{product.description}}" stepKey="fillFieldDescription"/> + <click selector="{{AdminUpdateAttributesSection.saveButton}}" stepKey="save"/> + <waitForElementVisible selector="{{AdminMessagesSection.successMessage}}" stepKey="waitVisibleSuccessMessage"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="Message is added to queue" stepKey="seeSuccessMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/CustomAttributeData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/CustomAttributeData.xml index 389c41abf0bd1..1684bd0c8a2c3 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/CustomAttributeData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/CustomAttributeData.xml @@ -35,4 +35,20 @@ <data key="attribute_code">news_from_date</data> <data key="value">2018-05-17 00:00:00</data> </entity> + <entity name="CustomDynamicProductDescription" type="custom_attribute"> + <data key="attribute_code">description</data> + <data key="value">Dynamicscription testing 321</data> + </entity> + <entity name="CustomDynamicProductShortDescription" type="custom_attribute"> + <data key="attribute_code">short_description</data> + <data key="value">Short dynamictest 555</data> + </entity> + <entity name="CustomFixedProductDescription" type="custom_attribute"> + <data key="attribute_code">description</data> + <data key="value">Fixedscription testing 321</data> + </entity> + <entity name="CustomFixedProductShortDescription" type="custom_attribute"> + <data key="attribute_code">short_description</data> + <data key="value">Short Fixedtest 555</data> + </entity> </entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeMassUpdateData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeMassUpdateData.xml new file mode 100644 index 0000000000000..99908f1c9df5f --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeMassUpdateData.xml @@ -0,0 +1,15 @@ +<?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="UpdateAttributeNameAndDescription" type="productAttributeMassUpdate"> + <data key="name" unique="suffix">New Bundle Product Name</data> + <data key="description" unique="suffix">This is the description</data> + </entity> +</entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminUpdateAttributesSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminUpdateAttributesSection.xml index 53af1d5bd6eb1..69d7297628d56 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminUpdateAttributesSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminUpdateAttributesSection.xml @@ -36,6 +36,7 @@ <element name="toggleWeight" type="checkbox" selector="#toggle_weight"/> <element name="toggleColor" type="checkbox" selector="#toggle_color"/> + <element name="name" type="input" selector="#name"/> <element name="description" type="input" selector="#description"/> </section> <section name="AdminUpdateAttributesWebsiteSection"> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/StorefrontCatalogSearchActionGroup.xml b/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/StorefrontCatalogSearchActionGroup.xml index 067d76821d687..34e86566d73ba 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/StorefrontCatalogSearchActionGroup.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/StorefrontCatalogSearchActionGroup.xml @@ -64,6 +64,13 @@ <see selector="{{StorefrontQuickSearchResultsSection.productByIndex(index)}}" userInput="{{productName}}" stepKey="seeProductName"/> </actionGroup> + <actionGroup name="StorefrontQuickSearchSeeProductByName"> + <arguments> + <argument name="productName" type="string"/> + </arguments> + <see selector="{{StorefrontQuickSearchResultsSection.productByName(productName)}}" userInput="{{productName}}" stepKey="seeProductName"/> + </actionGroup> + <actionGroup name="StorefrontQuickSearchCheckProductNameNotInGrid"> <arguments> <argument name="productName" type="string"/> diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/DeleteCustomStoreActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/DeleteCustomStoreActionGroup.xml index 8a1d830661aad..70fc08528f85e 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/DeleteCustomStoreActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/DeleteCustomStoreActionGroup.xml @@ -22,6 +22,8 @@ <click selector="{{AdminStoresMainActionsSection.deleteButton}}" stepKey="clickDeleteStoreGroupButtonOnEditStorePage"/> <selectOption userInput="No" selector="{{AdminStoresDeleteStoreGroupSection.createDbBackup}}" stepKey="setCreateDbBackupToNo"/> <click selector="{{AdminStoresDeleteStoreGroupSection.deleteStoreGroupButton}}" stepKey="clickDeleteStoreGroupButtonOnDeleteStorePage"/> + <waitForElementVisible selector="{{AdminMessagesSection.successMessage}}" stepKey="waitForSuccessMessage"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="You deleted the store." stepKey="seeSuccessMessage"/> </actionGroup> <actionGroup name="DeleteCustomStoreBackupEnabledYesActionGroup"> <arguments> @@ -52,4 +54,4 @@ <waitForPageLoad stepKey="waitForStoreToLoad"/> <see selector="{{AdminStoresGridSection.emptyText}}" userInput="We couldn't find any records." stepKey="seeAssertStoreGroupNotInGridMessage"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontAddMultipleStoreProductsToWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontAddMultipleStoreProductsToWishlistTest.xml index ede63322235f2..e8b645990390e 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontAddMultipleStoreProductsToWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontAddMultipleStoreProductsToWishlistTest.xml @@ -10,16 +10,14 @@ <test name="StorefrontAddMultipleStoreProductsToWishlistTest"> <annotations> <features value="Wishlist"/> - <stories value="Adding to wishlist"/> + <stories value="Add product to wishlist"/> <title value="Customer should be able to add products to wishlist from different stores"/> <description value="All products added to wishlist should be visible on any store. Even if product visibility was set to 'Not Visible Individually' for this store"/> <group value="wishlist"/> <severity value="AVERAGE"/> - <testCaseId value="MAGETWO-95678"/> - <skip> - <issueId value="MC-13867"/> - </skip> + <testCaseId value="MC-6243"/> </annotations> + <before> <createData entity="customStoreGroup" stepKey="storeGroup"/> <createData entity="SimpleSubCategory" stepKey="categoryHandle"/> @@ -36,6 +34,7 @@ <argument name="storeGroupName" value="$$storeGroup.group[name]$$"/> </actionGroup> </before> + <after> <deleteData createDataKey="product" stepKey="deleteFirstProduct"/> <deleteData createDataKey="secondProduct" stepKey="deleteSecondProduct"/> @@ -43,8 +42,16 @@ <actionGroup ref="DeleteCustomStoreActionGroup" stepKey="deleteCustomStoreGroup"> <argument name="storeGroupName" value="$$storeGroup.group[name]$$"/> </actionGroup> - <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> + <actionGroup ref="clearFiltersAdminDataGrid" stepKey="clearWebsitesGridFilter"/> + + <!--Clear products filter--> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> + <actionGroup ref="clearFiltersAdminDataGrid" stepKey="clearProductsFilters"/> + <!--Logout everywhere--> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> </after> + <!-- Change products visibility on store-view level --> <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForProduct1"> <argument name="product" value="$$product$$"/> @@ -52,7 +59,9 @@ <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="openEditProduct1"> <argument name="product" value="$$product$$"/> </actionGroup> + <scrollToTopOfPage stepKey="scrollToTopToChangeStore"/> <click selector="{{AdminProductFormActionSection.changeStoreButton}}" stepKey="clickSwitchStoreMenuForProduct1"/> + <waitForElementVisible selector="{{AdminProductFormChangeStoreSection.storeSelector(customStore.name)}}" stepKey="waitCustomStoreItemAppers"/> <click selector="{{AdminProductFormChangeStoreSection.storeSelector(customStore.name)}}" stepKey="clickOnStoreNameItemForProduct1"/> <waitForElementVisible selector="{{AdminProductFormChangeStoreSection.acceptButton}}" stepKey="waitAcceptStoreSwitchingForProduct1n"/> <click selector="{{AdminProductFormChangeStoreSection.acceptButton}}" stepKey="acceptStoreSwitchingForProduct1"/> @@ -65,36 +74,37 @@ <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="openEditProduct2"> <argument name="product" value="$$secondProduct$$"/> </actionGroup> + <scrollToTopOfPage stepKey="scrollToTopToChangeStoreAgain"/> <click selector="{{AdminProductFormActionSection.changeStoreButton}}" stepKey="clickSwitchStoreMenuForProduct2"/> + <waitForElementVisible selector="{{AdminProductFormChangeStoreSection.storeSelector(customStore.name)}}" stepKey="waitDefaultStoreItemAppers"/> <click selector="{{AdminProductFormChangeStoreSection.storeSelector('Default Store View')}}" stepKey="clickOnStoreNameItemForProduct2"/> <waitForElementVisible selector="{{AdminProductFormChangeStoreSection.acceptButton}}" stepKey="waitAcceptStoreSwitchingForProduct2"/> <click selector="{{AdminProductFormChangeStoreSection.acceptButton}}" stepKey="acceptStoreSwitchingForProduct2"/> <click selector="{{AdminProductFormSection.visibilityUseDefault}}" stepKey="uncheckVisibilityUseDefaultValueForProduct2"/> <selectOption userInput="Not Visible Individually" selector="{{AdminProductFormSection.visibility}}" stepKey="makeProductNotVisibleOnDefaultStoreView"/> <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveEditedProductForProduct2"/> + <!-- Sign in as customer --> - <amOnPage url="{{StorefrontCustomerSignInPage.url}}" stepKey="amOnSignInPage"/> - <fillField userInput="$$customer.email$$" selector="{{StorefrontCustomerSignInFormSection.emailField}}" stepKey="fillEmail"/> - <fillField userInput="$$customer.password$$" selector="{{StorefrontCustomerSignInFormSection.passwordField}}" stepKey="fillPassword"/> - <waitForElementVisible selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}" stepKey="waitForButton"/> - <click selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}" stepKey="clickSignInAccountButton"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> + <argument name="Customer" value="$$customer$$" /> + </actionGroup> <see userInput="$$customer.firstname$$" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}" stepKey="seeFirstName"/> <see userInput="$$customer.lastname$$" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}" stepKey="seeLastName"/> <see userInput="$$customer.email$$" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}" stepKey="seeEmail"/> <!-- Add product visible on default store to wishlist --> - <amOnPage url="$$product.name$$.html" stepKey="navigateToProductPageOnDefaultStore"/> + <amOnPage url="{{StorefrontProductPage.url($$product.custom_attributes[url_key]$$)}}" stepKey="navigateToProductPageOnDefaultStore"/> <see userInput="$$product.name$$" selector="{{StorefrontProductInfoMainSection.productName}}" stepKey="assertFirstProductNameTitle"/> <click selector="{{StorefrontProductPageSection.addToWishlist}}" stepKey="addFirstProductToWishlist"/> <!-- Switch to second store and add second product (visible on second store) to wishlist --> - <click selector="{{StorefrontFooterSection.switchStoreButton}}" stepKey="ClickSwitchStoreButtonOnDefaultStore"/> - <click selector="{{StorefrontFooterSection.storeLink($$storeGroup.group[name]$$)}}" stepKey="SelectSecondStoreToSwitchOn"/> + <click selector="{{StorefrontFooterSection.switchStoreButton}}" stepKey="clickSwitchStoreButtonOnDefaultStore"/> + <click selector="{{StorefrontFooterSection.storeLink($$storeGroup.group[name]$$)}}" stepKey="selectSecondStoreToSwitchOn"/> <!-- Verify that both products are visible in wishlist on both stores --> - <amOnPage url="$$secondProduct.name$$.html" stepKey="navigateToProductPageOnSecondStore"/> + <amOnPage url="{{StorefrontProductPage.url($$secondProduct.custom_attributes[url_key]$$)}}" stepKey="navigateToProductPageOnSecondStore"/> <see userInput="$$secondProduct.name$$" selector="{{StorefrontProductInfoMainSection.productName}}" stepKey="assertSecondProductNameTitle"/> <click selector="{{StorefrontProductPageSection.addToWishlist}}" stepKey="addSecondProductToWishlist"/> <see userInput="$$secondProduct.name$$" selector="{{StorefrontCustomerWishlistSection.productItemNameText}}" stepKey="seeProduct2InWishlistOnSecondStore"/> - <click selector="{{StorefrontFooterSection.switchStoreButton}}" stepKey="ClickSwitchStoreButtonOnSecondStore"/> - <click selector="{{StorefrontFooterSection.storeLink('Main Website Store')}}" stepKey="SelectDefaultStoreToSwitchOn"/> + <click selector="{{StorefrontFooterSection.switchStoreButton}}" stepKey="clickSwitchStoreButtonOnSecondStore"/> + <click selector="{{StorefrontFooterSection.storeLink('Main Website Store')}}" stepKey="selectDefaultStoreToSwitchOn"/> <see userInput="$$product.name$$" selector="{{StorefrontCustomerWishlistSection.productItemNameText}}" stepKey="seeProduct1InWishlistOnDefaultStore"/> </test> </tests> diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php index 62a44f851e405..bb8e246b573eb 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php @@ -6,21 +6,51 @@ namespace Magento\Sales\Service\V1; +use Magento\Framework\ObjectManagerInterface; +use Magento\Sales\Model\Order; +use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\WebapiAbstract; +/** + * Canceling of the order + */ class OrderCancelTest extends WebapiAbstract { const SERVICE_VERSION = 'V1'; - const SERVICE_NAME = 'salesOrderManagementV1'; /** - * @magentoApiDataFixture Magento/Sales/_files/order.php + * @var ObjectManagerInterface */ - public function testOrderCancel() + private $objectManager; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + } + + /** + * Gets order by increment ID. + * + * @param string $incrementId + * @return Order + */ + private function getOrder(string $incrementId): Order + { + return $this->objectManager->create(Order::class)->loadByIncrementId($incrementId); + } + + /** + * Send API request for canceling the order + * + * @param Order $order + * @return array|bool|float|int|string + */ + private function sendCancelRequest(Order $order) { - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $order = $objectManager->get(\Magento\Sales\Model\Order::class)->loadByIncrementId('100000001'); $serviceInfo = [ 'rest' => [ 'resourcePath' => '/V1/orders/' . $order->getId() . '/cancel', @@ -33,7 +63,36 @@ public function testOrderCancel() ], ]; $requestData = ['id' => $order->getId()]; - $result = $this->_webApiCall($serviceInfo, $requestData); + return $this->_webApiCall($serviceInfo, $requestData); + } + + /** + * @magentoApiDataFixture Magento/Sales/_files/order.php + */ + public function testOrderCancel() + { + $order = $this->getOrder('100000001'); + $result = $this->sendCancelRequest($order); $this->assertTrue($result); } + + /** + * @magentoApiDataFixture Magento/Sales/_files/order_state_hold.php + */ + public function testOrderWithStateHoldedShouldNotBeCanceled() + { + $order = $this->getOrder('100000001'); + $result = $this->sendCancelRequest($order); + $this->assertFalse($result); + } + + /** + * @magentoApiDataFixture Magento/Sales/_files/order_with_shipping_and_invoice.php + */ + public function testOrderWithStateCompleteShouldNotBeCanceled() + { + $order = $this->getOrder('100000001'); + $result = $this->sendCancelRequest($order); + $this->assertFalse($result); + } } diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php index e2a156cc6fbfc..049f49c93c7cd 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php @@ -5,6 +5,12 @@ */ namespace Magento\Sales\Service\V1; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Sales\Api\Data\OrderItemInterface; +use Magento\Sales\Api\ShipmentRepositoryInterface; +use Magento\Sales\Model\Order; + /** * API test for creation of Shipment for certain Order. */ @@ -14,22 +20,28 @@ class ShipOrderTest extends \Magento\TestFramework\TestCase\WebapiAbstract const SERVICE_VERSION = 'V1'; /** - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ private $objectManager; /** - * @var \Magento\Sales\Api\ShipmentRepositoryInterface + * @var ShipmentRepositoryInterface */ private $shipmentRepository; + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @inheritdoc + */ protected function setUp() { $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - - $this->shipmentRepository = $this->objectManager->get( - \Magento\Sales\Api\ShipmentRepositoryInterface::class - ); + $this->shipmentRepository = $this->objectManager->get(ShipmentRepositoryInterface::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); } /** @@ -40,9 +52,8 @@ public function testConfigurableShipOrder() $this->markTestIncomplete('https://github.com/magento-engcom/msi/issues/1335'); $productsQuantity = 1; - /** @var \Magento\Sales\Model\Order $existingOrder */ - $existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) - ->loadByIncrementId('100000001'); + /** @var Order $existingOrder */ + $existingOrder = $this->getOrder('100000001'); $requestData = [ 'orderId' => $existingOrder->getId(), @@ -83,9 +94,8 @@ public function testConfigurableShipOrder() */ public function testShipOrder() { - /** @var \Magento\Sales\Model\Order $existingOrder */ - $existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) - ->loadByIncrementId('100000001'); + /** @var Order $existingOrder */ + $existingOrder = $this->getOrder('100000001'); $requestData = [ 'orderId' => $existingOrder->getId(), @@ -103,7 +113,7 @@ public function testShipOrder() ] ]; - /** @var \Magento\Sales\Api\Data\OrderItemInterface $item */ + /** @var OrderItemInterface $item */ foreach ($existingOrder->getAllItems() as $item) { $requestData['items'][] = [ 'order_item_id' => $item->getItemId(), @@ -121,9 +131,8 @@ public function testShipOrder() $this->fail('Failed asserting that Shipment was created'); } - /** @var \Magento\Sales\Model\Order $updatedOrder */ - $updatedOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) - ->loadByIncrementId('100000001'); + /** @var Order $updatedOrder */ + $updatedOrder = $this->getOrder('100000001'); $this->assertNotEquals( $existingOrder->getStatus(), @@ -144,9 +153,8 @@ public function testShipOrderWithoutTrackingNumberReturnsError() { $this->_markTestAsRestOnly('SOAP requires an tracking number to be provided so this case is not possible.'); - /** @var \Magento\Sales\Model\Order $existingOrder */ - $existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) - ->loadByIncrementId('100000001'); + /** @var Order $existingOrder */ + $existingOrder = $this->getOrder('100000001'); $requestData = [ 'orderId' => $existingOrder->getId(), @@ -170,9 +178,7 @@ public function testShipOrderWithoutTrackingNumberReturnsError() */ public function testPartialShipOrderWithBundleShippedSeparately() { - /** @var \Magento\Sales\Model\Order $existingOrder */ - $existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) - ->loadByIncrementId('100000001'); + $existingOrder = $this->getOrder('100000001'); $requestData = [ 'orderId' => $existingOrder->getId(), @@ -213,9 +219,8 @@ public function testPartialShipOrderWithBundleShippedSeparately() $this->assertEquals(1, $shipment->getTotalQty()); - /** @var \Magento\Sales\Model\Order $existingOrder */ - $existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) - ->loadByIncrementId('100000001'); + /** @var Order $existingOrder */ + $existingOrder = $this->getOrder('100000001'); foreach ($existingOrder->getAllItems() as $item) { if ($item->getItemId() == $shippedItemId) { @@ -227,10 +232,73 @@ public function testPartialShipOrderWithBundleShippedSeparately() } /** - * @param \Magento\Sales\Model\Order $order + * @magentoApiDataFixture Magento/Bundle/_files/order_with_2_bundles_shipping_separately.php + */ + public function testPartialShipOrderWithTwoBundleShippedSeparatelyContainsSameSimple() + { + $order = $this->getOrder('order_bundle_separately_shipped'); + + $requestData = [ + 'orderId' => $order->getId(), + 'items' => [], + 'comment' => [ + 'comment' => 'Test Comment', + 'is_visible_on_front' => 1, + ], + 'tracks' => [], + ]; + + $shippedItemId = null; + $parentItemId = null; + foreach ($order->getAllItems() as $item) { + if ($item->getSku() === 'simple1') { + $requestData['items'][] = [ + 'order_item_id' => $item->getItemId(), + 'qty' => $item->getQtyOrdered(), + ]; + $shippedItemId = $item->getItemId(); + $parentItemId = $item->getParentItemId(); + break; + } + } + + $shipmentId = $this->_webApiCall($this->getServiceInfo($order), $requestData); + $this->assertNotEmpty($shipmentId); + + try { + $shipment = $this->shipmentRepository->get($shipmentId); + } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { + $this->fail('Failed asserting that Shipment was created'); + } + + $this->assertEquals(1, $shipment->getTotalQty()); + + $order = $this->getOrder('order_bundle_separately_shipped'); + + foreach ($order->getAllItems() as $item) { + if (in_array($item->getItemId(), [$shippedItemId, $parentItemId])) { + $this->assertEquals(1, $item->getQtyShipped()); + continue; + } + $this->assertEquals(0, $item->getQtyShipped()); + } + + try { + $this->_webApiCall($this->getServiceInfo($order), $requestData); + $this->fail('Expected exception was not raised'); + } catch (\Exception $exception) { + $this->assertExceptionMessage( + $exception, + 'Shipment Document Validation Error(s): You can\'t create a shipment without products.' + ); + } + } + + /** + * @param Order $order * @return array */ - private function getServiceInfo(\Magento\Sales\Model\Order $order) + private function getServiceInfo(Order $order): array { $serviceInfo = [ 'rest' => [ @@ -243,6 +311,41 @@ private function getServiceInfo(\Magento\Sales\Model\Order $order) 'operation' => self::SERVICE_READ_NAME . 'execute', ], ]; + return $serviceInfo; } + + /** + * Returns order by increment id. + * + * @param string $incrementId + * @return Order + */ + private function getOrder(string $incrementId): Order + { + return $this->objectManager->create(Order::class)->loadByIncrementId($incrementId); + } + + /** + * Assert correct exception message. + * + * @param \Exception $exception + * @param string $expectedMessage + * @return void + */ + private function assertExceptionMessage(\Exception $exception, string $expectedMessage): void + { + $actualMessage = ''; + switch (TESTS_WEB_API_ADAPTER) { + case self::ADAPTER_SOAP: + $actualMessage = trim(preg_replace('/\s+/', ' ', $exception->getMessage())); + break; + case self::ADAPTER_REST: + $error = $this->processRestExceptionResult($exception); + $actualMessage = $error['message']; + break; + } + + $this->assertEquals($expectedMessage, $actualMessage); + } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately.php new file mode 100644 index 0000000000000..11d99ef59f911 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately.php @@ -0,0 +1,97 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Option; +use Magento\Bundle\Model\Product\Type as BundleProductType; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Checkout\Model\Cart; +use Magento\Checkout\Model\Session; +use Magento\Quote\Api\CartManagementInterface; +use Magento\Quote\Model\Quote\Address; +use Magento\Quote\Model\Quote\Payment; +use Magento\Quote\Model\QuoteManagement; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/two_bundle_products_with_separate_shipping.php'; +$addressData = include __DIR__ . '/../../../Magento/Sales/_files/address_data.php'; + +$objectManager = Bootstrap::getObjectManager(); +$billingAddress = $objectManager->create(Address::class, ['data' => $addressData]); +$billingAddress->setAddressType('billing'); + +$shippingAddress = clone $billingAddress; +$shippingAddress->setId(null) + ->setAddressType('shipping') + ->setShippingMethod('flatrate_flatrate'); + +/** @var Payment $payment */ +$payment = $objectManager->create(Payment::class); +$payment->setMethod('checkmo'); + +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->create(ProductRepositoryInterface::class); + +$bundleProduct = $productRepository->get('bundle-product-separate-shipping-1'); +$bundleProduct2 = $productRepository->get('bundle-product-separate-shipping-2'); +$selectionProducts = [ + $bundleProduct->getId() => [10, 12], + $bundleProduct2->getId() => [11, 13], +]; + +/** @var Cart $cart */ +$cart = $objectManager->create(Cart::class); + +foreach ([$bundleProduct, $bundleProduct2] as $product) { + + /** @var BundleProductType $typeInstance */ + $typeInstance = $product->getTypeInstance(); + $typeInstance->setStoreFilter($product->getStoreId(), $product); + $optionCollection = $typeInstance->getOptionsCollection($product); + + $bundleOptions = []; + $bundleOptionsQty = []; + $optionsData = []; + + /** @var Option $option */ + foreach ($optionCollection as $option) { + $selectionsCollection = $typeInstance->getSelectionsCollection([$option->getId()], $product); + $selectionIds = $selectionProducts[$product->getId()]; + $selectionsCollection->addIdFilter($selectionIds); + + foreach ($selectionIds as $productId) { + $selection = $selectionsCollection->getItemByColumnValue('product_id', $productId); + if ($selection !== null) { + $bundleOptions[$option->getId()] = $selection->getSelectionId(); + $optionsData[$option->getId()] = $selection->getProductId(); + $bundleOptionsQty[$option->getId()] = 1; + } + } + } + + $requestInfo = [ + 'product' => $product->getId(), + 'bundle_option' => $bundleOptions, + 'bundle_option_qty' => $bundleOptionsQty, + 'qty' => 1, + ]; + + $cart->addProduct($product, $requestInfo); +} + +$cart->getQuote() + ->setReservedOrderId('order_bundle_separately_shipped') + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setCheckoutMethod(CartManagementInterface::METHOD_GUEST) + ->setPayment($payment); +$cart->save(); + +/** @var QuoteManagement $quoteManager */ +$quoteManager = $objectManager->get(QuoteManagement::class); +$orderId = $quoteManager->placeOrder($cart->getQuote()->getId()); + +$objectManager->removeSharedInstance(Session::class); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately_rollback.php new file mode 100644 index 0000000000000..96e3adb65a7d6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately_rollback.php @@ -0,0 +1,8 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +require __DIR__ . '/../../../Magento/Sales/_files/default_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping.php new file mode 100644 index 0000000000000..5521b16354085 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping.php @@ -0,0 +1,115 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Api\Data\LinkInterfaceFactory; +use Magento\Bundle\Api\Data\OptionInterfaceFactory; +use Magento\Bundle\Model\Product\Price as BundlePrice; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type as BundleProductType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/multiple_products.php'; + +$objectManager = Bootstrap::getObjectManager(); + +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->create(ProductRepositoryInterface::class); + +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->create(ProductFactory::class); + +/** @var OptionInterfaceFactory $bundleOptionFactory */ +$bundleOptionFactory = $objectManager->create(OptionInterfaceFactory::class); + +/** @var LinkInterfaceFactory $bundleLinkFactory */ +$bundleLinkFactory = $objectManager->create(LinkInterfaceFactory::class); + +$bundleProduct = $productFactory->create(); +$attributeSetId = $bundleProduct->getDefaultAttributeSetId(); +$bundleProduct->setTypeId(BundleProductType::TYPE_BUNDLE) + ->setAttributeSetId($attributeSetId) + ->setWebsiteIds([1]) + ->setName('Bundle Product With Separate Items Shipping') + ->setSku('bundle-product-separate-shipping-1') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(1) + ->setPriceType(BundlePrice::PRICE_TYPE_FIXED) + ->setPrice(10.0) + ->setShipmentType(1) + ->setBundleOptionsData( + [ + [ + 'title' => 'Option 1', + 'default_title' => 'Option 1', + 'type' => 'radio', + 'required' => 1, + 'delete' => '', + ], + [ + 'title' => 'Option 2', + 'default_title' => 'Option 2', + 'type' => 'radio', + 'required' => 1, + 'delete' => '', + ], + ] + )->setBundleSelectionsData( + [ + [ + ['product_id' => 10, 'selection_qty' => 1, 'selection_can_change_qty' => 1, 'delete' => ''], + ['product_id' => 11, 'selection_qty' => 1, 'selection_can_change_qty' => 1, 'delete' => ''], + ], + [ + ['product_id' => 12, 'selection_qty' => 1, 'selection_can_change_qty' => 1, 'delete' => ''], + ['product_id' => 13, 'selection_qty' => 1, 'selection_can_change_qty' => 1, 'delete' => ''], + ], + ] + ); + +$bundleProduct2 = $productFactory->create(['data' => $bundleProduct->getData()]); +$bundleProduct2 + ->setName('Bundle Product With Separate Items Shipping Two') + ->setSku('bundle-product-separate-shipping-2'); + +foreach ([$bundleProduct, $bundleProduct2] as $product) { + if ($product->getBundleOptionsData()) { + $options = []; + foreach ($product->getBundleOptionsData() as $key => $optionData) { + if (!(bool)$optionData['delete']) { + $option = $bundleOptionFactory->create(['data' => $optionData]); + $option->setSku($product->getSku()); + $option->setOptionId(null); + + $links = []; + $bundleLinks = $product->getBundleSelectionsData(); + if (!empty($bundleLinks[$key])) { + foreach ($bundleLinks[$key] as $linkData) { + if (!(bool)$linkData['delete']) { + $link = $bundleLinkFactory->create(['data' => $linkData]); + $linkProduct = $productRepository->getById($linkData['product_id']); + $link->setSku($linkProduct->getSku()); + $link->setQty($linkData['selection_qty']); + $links[] = $link; + } + } + $option->setProductLinks($links); + $options[] = $option; + } + } + } + $extension = $product->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $product->setExtensionAttributes($extension); + } + + $productRepository->save($product, true); +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping_rollback.php new file mode 100644 index 0000000000000..c2c4d992d763e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping_rollback.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Registry; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); + +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $productRepository->deleteById('bundle-product-separate-shipping-1'); + $productRepository->deleteById('bundle-product-separate-shipping-2'); +} catch (NoSuchEntityException $exception) { + // When DbIsolation is used products can be already removed by rollback main transaction +} + +$registry->register('isSecureArea', false); + +require __DIR__ . '/multiple_products_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_state_hold.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_state_hold.php new file mode 100644 index 0000000000000..5578a55b57e8b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_state_hold.php @@ -0,0 +1,15 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Sales\Model\Order; + +require __DIR__ . '/order.php'; + +/** @var Order $order */ +$order->setState(Order::STATE_HOLDED); +$order->setStatus(Order::STATE_HOLDED); +$order->save();