Skip to content

Commit a4716ad

Browse files
ENGCOM-8062: Fix #24091 - Selected configurable product attribute options are not displaying in wishlist page. #28157
2 parents 53bd497 + 7775a51 commit a4716ad

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)