Skip to content

Commit 7775a51

Browse files
ENGCOM-8062: Fix #24091 - Selected configurable product attribute options are not displaying in wishlist page. #28157
- Merge Pull Request #28157 from Bartlomiejsz/magento2:feature/fix_24091_configurable_product_options_on_wishlist - Merged commits: 1. a128f39 2. e3bad69 3. 536a728 4. 3d69b13 5. 75a5f25 6. 0471e4e 7. 2c07389 8. e3e5a9a 9. e378086 10. 11abbf9 11. ac6be80 12. 8eead95 13. e3fd246 14. 129f451 15. 8d02533 16. 840c99c
2 parents afd7ecc + 840c99c commit 7775a51

9 files changed

+258
-43
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AddVisualSwatchToProductWithOutCreatedActionGroup">
12+
<annotations>
13+
<description>Does not create an attribute. Adds the provided Visual Swatch Attribute and Options (2) to a Product on the Admin Product creation/edit page. Clicks on Save. Validates that the Success Message is present. </description>
14+
</annotations>
15+
<arguments>
16+
<argument name="attribute" defaultValue="visualSwatchAttribute"/>
17+
</arguments>
18+
19+
<seeInCurrentUrl url="{{ProductCatalogPage.url}}" stepKey="seeOnProductEditPage"/>
20+
<conditionalClick selector="{{AdminProductFormConfigurationsSection.sectionHeader}}" dependentSelector="{{AdminProductFormConfigurationsSection.createConfigurations}}" visible="false" stepKey="openConfigurationSection"/>
21+
<click selector="{{AdminProductFormConfigurationsSection.createConfigurations}}" stepKey="openConfigurationPanel"/>
22+
<waitForElementVisible selector="{{AdminCreateProductConfigurationsPanel.createNewAttribute}}" stepKey="waitForSlideOut"/>
23+
24+
<!--Find attribute in grid and select-->
25+
<conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearExistingFilters"/>
26+
<click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="clickOnFilters"/>
27+
<fillField selector="{{AdminDataGridHeaderSection.attributeCodeFilterInput}}" userInput="{{attribute.default_label}}" stepKey="fillFilterAttributeCodeField"/>
28+
<click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickApplyFiltersButton"/>
29+
<click selector="{{AdminDataGridTableSection.rowCheckbox('1')}}" stepKey="clickOnFirstCheckbox"/>
30+
31+
<click selector="{{AdminCreateProductConfigurationsPanel.next}}" stepKey="clickNextStep1"/>
32+
33+
<click selector="{{AdminCreateProductConfigurationsPanel.selectAllByAttribute(attribute.default_label)}}" stepKey="clickSelectAll"/>
34+
<click selector="{{AdminCreateProductConfigurationsPanel.next}}" stepKey="clickNextStep2"/>
35+
36+
<click selector="{{AdminCreateProductConfigurationsPanel.applySingleQuantityToEachSkus}}" stepKey="clickOnApplySingleQuantityToEachSku"/>
37+
<fillField selector="{{AdminCreateProductConfigurationsPanel.quantity}}" userInput="100" stepKey="enterAttributeQuantity"/>
38+
<click selector="{{AdminCreateProductConfigurationsPanel.next}}" stepKey="clickOnNextStep3"/>
39+
<click selector="{{AdminCreateProductConfigurationsPanel.next}}" stepKey="generateProducts"/>
40+
<click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveProduct"/>
41+
<seeElement selector="{{AdminMessagesSection.success}}" stepKey="seeSaveProductMessage"/>
42+
</actionGroup>
43+
</actionGroups>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<!--Click a swatch option on product page-->
12+
<actionGroup name="StorefrontSelectVisualSwatchOptionOnCategoryPageActionGroup">
13+
<arguments>
14+
<argument name="productId" type="string"/>
15+
<argument name="visualSwatchOptionLabel" type="string" />
16+
</arguments>
17+
<click selector="{{StorefrontCategoryPageProductInfoSection.visualSwatchOption(productId,visualSwatchOptionLabel)}}" stepKey="clickSwatchOption"/>
18+
</actionGroup>
19+
</actionGroups>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
11+
<section name="StorefrontCategoryPageProductInfoSection">
12+
<element name="visualSwatchOption" type="button" selector="#product-item-info_{{var1}} .swatch-option[data-option-label='{{var2}}']" parameterized="true"/>
13+
<element name="productAddToWishlist" type="button" selector="#product-item-info_{{var1}} .action.towishlist" parameterized="true"/>
14+
</section>
15+
</sections>

app/code/Magento/Wishlist/Block/AddToWishlist.php

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@
66

77
namespace Magento\Wishlist\Block;
88

9+
use Magento\Catalog\Api\Data\ProductTypeInterface;
10+
use Magento\Catalog\Api\ProductTypeListInterface;
11+
use Magento\Framework\App\ObjectManager;
12+
use Magento\Framework\View\Element\Template;
13+
use Magento\Framework\View\Element\Template\Context;
14+
915
/**
1016
* Wishlist js plugin initialization block
1117
*
1218
* @api
1319
* @since 100.1.0
1420
*/
15-
class AddToWishlist extends \Magento\Framework\View\Element\Template
21+
class AddToWishlist extends Template
1622
{
1723
/**
1824
* Product types
@@ -22,17 +28,25 @@ class AddToWishlist extends \Magento\Framework\View\Element\Template
2228
private $productTypes;
2329

2430
/**
25-
* @param \Magento\Framework\View\Element\Template\Context $context
31+
* @var ProductTypeListInterface
32+
*/
33+
private $productTypeList;
34+
35+
/**
36+
* AddToWishlist constructor.
37+
*
38+
* @param Context $context
2639
* @param array $data
40+
* @param ProductTypeListInterface|null $productTypeList
2741
*/
2842
public function __construct(
29-
\Magento\Framework\View\Element\Template\Context $context,
30-
array $data = []
43+
Context $context,
44+
array $data = [],
45+
?ProductTypeListInterface $productTypeList = null
3146
) {
32-
parent::__construct(
33-
$context,
34-
$data
35-
);
47+
parent::__construct($context, $data);
48+
$this->productTypes = [];
49+
$this->productTypeList = $productTypeList ?: ObjectManager::getInstance()->get(ProductTypeListInterface::class);
3650
}
3751

3852
/**
@@ -49,36 +63,16 @@ public function getWishlistOptions()
4963
/**
5064
* Returns an array of product types
5165
*
52-
* @return array|null
53-
* @throws \Magento\Framework\Exception\LocalizedException
66+
* @return array
5467
*/
55-
private function getProductTypes()
68+
private function getProductTypes(): array
5669
{
57-
if ($this->productTypes === null) {
58-
$this->productTypes = [];
59-
$block = $this->getLayout()->getBlock('category.products.list');
60-
if ($block) {
61-
$productCollection = $block->getLoadedProductCollection();
62-
$productTypes = [];
63-
/** @var $product \Magento\Catalog\Model\Product */
64-
foreach ($productCollection as $product) {
65-
$productTypes[] = $this->escapeHtml($product->getTypeId());
66-
}
67-
$this->productTypes = array_unique($productTypes);
68-
}
70+
if (count($this->productTypes) === 0) {
71+
/** @var ProductTypeInterface productTypes */
72+
$this->productTypes = array_map(function ($productType) {
73+
return $productType->getName();
74+
}, $this->productTypeList->getProductTypes());
6975
}
7076
return $this->productTypes;
7177
}
72-
73-
/**
74-
* {@inheritdoc}
75-
* @since 100.1.0
76-
*/
77-
protected function _toHtml()
78-
{
79-
if (!$this->getProductTypes()) {
80-
return '';
81-
}
82-
return parent::_toHtml();
83-
}
8478
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="StorefrontCustomerAddProductToWishlistCategoryPageActionGroup">
12+
<annotations>
13+
<description>Adds the provided Product to the Wish List from the Storefront Category page. Validates that the Success Message is present and correct.</description>
14+
</annotations>
15+
<arguments>
16+
<argument name="productVar"/>
17+
</arguments>
18+
19+
<click selector="{{StorefrontCategoryPageProductInfoSection.productAddToWishlist(productVar.id)}}" stepKey="addProductToWishlistClickAddToWishlist"/>
20+
<waitForElement selector="{{StorefrontCustomerWishlistSection.successMsg}}" time="30" stepKey="addProductToWishlistWaitForSuccessMessage"/>
21+
<see selector="{{StorefrontCustomerWishlistSection.successMsg}}" userInput="{{productVar.name}} has been added to your Wish List. Click here to continue shopping." stepKey="addProductToWishlistSeeProductNameAddedToWishlist"/>
22+
<seeCurrentUrlMatches regex="~/wishlist_id/\d+/$~" stepKey="seeCurrentUrlMatches"/>
23+
</actionGroup>
24+
</actionGroups>
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
11+
<test name="StorefrontCheckOptionsConfigurableProductInWishlistTest">
12+
<annotations>
13+
<stories value="Wishlist"/>
14+
<title value="Move first Configurable Product with selected optional from Category Page to Wishlist."/>
15+
<description value="Move first Configurable Product with selected optional from Category Page to Wishlist. On Page will be present minimum two Configurable Product"/>
16+
<severity value="CRITICAL"/>
17+
<testCaseId value="MC-14211"/>
18+
<group value="wishlist"/>
19+
</annotations>
20+
<before>
21+
<createData entity="ApiCategory" stepKey="createCategory"/>
22+
<createData entity="ApiConfigurableProduct" stepKey="createFirstConfigProduct">
23+
<requiredEntity createDataKey="createCategory"/>
24+
</createData>
25+
<createData entity="ApiConfigurableProduct" stepKey="createSecondConfigProduct">
26+
<requiredEntity createDataKey="createCategory"/>
27+
</createData>
28+
<createData entity="Simple_US_Customer" stepKey="customer"/>
29+
<actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex">
30+
<argument name="indices" value=""/>
31+
</actionGroup>
32+
<actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache">
33+
<argument name="tags" value=""/>
34+
</actionGroup>
35+
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
36+
</before>
37+
<after>
38+
<deleteData createDataKey="customer" stepKey="deleteCustomer"/>
39+
<actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteFirstProducts">
40+
<argument name="sku" value="$$createFirstConfigProduct.sku$$"/>
41+
</actionGroup>
42+
<actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteSecondProducts">
43+
<argument name="sku" value="$$createSecondConfigProduct.sku$$"/>
44+
</actionGroup>
45+
<deleteData createDataKey="createCategory" stepKey="deleteCategory"/>
46+
<actionGroup ref="AdminDeleteProductAttributeByLabelActionGroup" stepKey="deleteAttribute" >
47+
<argument name="productAttributeLabel" value="{{visualSwatchAttribute.default_label}}"/>
48+
</actionGroup>
49+
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>
50+
<actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex">
51+
<argument name="indices" value=""/>
52+
</actionGroup>
53+
<actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache">
54+
<argument name="tags" value=""/>
55+
</actionGroup>
56+
</after>
57+
<actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="navigateToFirstConfigProductPage">
58+
<argument name="productId" value="$$createFirstConfigProduct.id$$"/>
59+
</actionGroup>
60+
<waitForPageLoad stepKey="waitForFirstProductPageLoad"/>
61+
<actionGroup ref="AddVisualSwatchToProductWithStorefrontConfigActionGroup" stepKey="addSwatchToFirstProduct">
62+
<argument name="attribute" value="visualSwatchAttribute"/>
63+
<argument name="option1" value="visualSwatchOption1"/>
64+
<argument name="option2" value="visualSwatchOption2"/>
65+
</actionGroup>
66+
67+
<actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="navigateToSecondConfigProductPage">
68+
<argument name="productId" value="$$createSecondConfigProduct.id$$"/>
69+
</actionGroup>
70+
<waitForPageLoad stepKey="waitForSecondProductPageLoad"/>
71+
<actionGroup ref="AddVisualSwatchToProductWithOutCreatedActionGroup" stepKey="addSwatchToSecondProduct">
72+
<argument name="attribute" value="visualSwatchAttribute"/>
73+
</actionGroup>
74+
75+
<actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount">
76+
<argument name="Customer" value="$$customer$$"/>
77+
</actionGroup>
78+
<actionGroup ref="StorefrontGoToCategoryPageActionGroup" stepKey="openCategoryPage">
79+
<argument name="categoryName" value="$$createCategory.name$$"/>
80+
</actionGroup>
81+
<actionGroup ref="StorefrontSelectVisualSwatchOptionOnCategoryPageActionGroup" stepKey="selectVisualSwatch">
82+
<argument name="productId" value="$$createFirstConfigProduct.id$$" />
83+
<argument name="visualSwatchOptionLabel" value="{{visualSwatchOption1.default_label}}" />
84+
</actionGroup>
85+
<actionGroup ref="StorefrontCustomerAddProductToWishlistCategoryPageActionGroup" stepKey="addToWishlistProduct">
86+
<argument name="productVar" value="$$createFirstConfigProduct$$"/>
87+
</actionGroup>
88+
89+
<seeElement selector="{{StorefrontCustomerWishlistProductSection.productSeeDetailsByName($$createFirstConfigProduct.name$$)}}" stepKey="seeDetails"/>
90+
</test>
91+
</tests>

app/code/Magento/Wishlist/view/frontend/layout/catalog_category_view.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
template="Magento_Wishlist::catalog/product/list/addto/wishlist.phtml"/>
2222
</referenceBlock>
2323
<referenceContainer name="category.product.list.additional">
24-
<block class="Magento\Wishlist\Block\AddToWishlist" name="category.product.list.additional.wishlist_addto" template="Magento_Wishlist::addto.phtml" />
24+
<block class="Magento\Wishlist\Block\AddToWishlist"
25+
name="category.product.list.additional.wishlist_addto"
26+
template="Magento_Wishlist::addto.phtml"/>
2527
</referenceContainer>
2628
</referenceContainer>
2729
</body>

app/code/Magento/Wishlist/view/frontend/layout/catalogsearch_result_index.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,10 @@
1414
template="Magento_Wishlist::catalog/product/list/addto/wishlist.phtml"/>
1515
</referenceBlock>
1616
</referenceContainer>
17+
<referenceBlock name="wishlist_page_head_components">
18+
<block class="Magento\Wishlist\Block\AddToWishlist"
19+
name="catalogsearch.wishlist_addto"
20+
template="Magento_Wishlist::addto.phtml"/>
21+
</referenceBlock>
1722
</body>
1823
</page>

app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.js

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ define([
1717
downloadableInfo: '#downloadable-links-list input',
1818
customOptionsInfo: '.product-custom-option',
1919
qtyInfo: '#qty',
20-
actionElement: '[data-action="add-to-wishlist"]'
20+
actionElement: '[data-action="add-to-wishlist"]',
21+
productListWrapper: '.product-item-info',
22+
productPageWrapper: '.product-info-main'
2123
},
2224

2325
/** @inheritdoc */
@@ -65,15 +67,19 @@ define([
6567
_updateWishlistData: function (event) {
6668
var dataToAdd = {},
6769
isFileUploaded = false,
70+
handleObjSelector = null,
6871
self = this;
6972

7073
if (event.handleObj.selector == this.options.qtyInfo) { //eslint-disable-line eqeqeq
71-
this._updateAddToWishlistButton({});
74+
this._updateAddToWishlistButton({}, event);
7275
event.stopPropagation();
7376

7477
return;
7578
}
76-
$(event.handleObj.selector).each(function (index, element) {
79+
80+
handleObjSelector = $(event.currentTarget).closest('form').find(event.handleObj.selector);
81+
82+
handleObjSelector.each(function (index, element) {
7783
if ($(element).is('input[type=text]') ||
7884
$(element).is('input[type=email]') ||
7985
$(element).is('input[type=number]') ||
@@ -98,18 +104,20 @@ define([
98104
if (isFileUploaded) {
99105
this.bindFormSubmit();
100106
}
101-
this._updateAddToWishlistButton(dataToAdd);
107+
this._updateAddToWishlistButton(dataToAdd, event);
102108
event.stopPropagation();
103109
},
104110

105111
/**
106112
* @param {Object} dataToAdd
113+
* @param {jQuery.Event} event
107114
* @private
108115
*/
109-
_updateAddToWishlistButton: function (dataToAdd) {
110-
var self = this;
116+
_updateAddToWishlistButton: function (dataToAdd, event) {
117+
var self = this,
118+
buttons = this._getAddToWishlistButton(event);
111119

112-
$('[data-action="add-to-wishlist"]').each(function (index, element) {
120+
buttons.each(function (index, element) {
113121
var params = $(element).data('post');
114122

115123
if (!params) {
@@ -125,6 +133,20 @@ define([
125133
});
126134
},
127135

136+
/**
137+
* @param {jQuery.Event} event
138+
* @private
139+
*/
140+
_getAddToWishlistButton: function (event) {
141+
var productListWrapper = $(event.currentTarget).closest(this.options.productListWrapper);
142+
143+
if (productListWrapper.length) {
144+
return productListWrapper.find(this.options.actionElement);
145+
}
146+
147+
return $(event.currentTarget).closest(this.options.productPageWrapper).find(this.options.actionElement);
148+
},
149+
128150
/**
129151
* @param {Object} array1
130152
* @param {Object} array2

0 commit comments

Comments
 (0)