Skip to content

Commit e885088

Browse files
Merge pull request #10130 from adobe-commerce-tier-4/PR_2025_10_01_flowers
[Support Tier-4 flowers] 10-01-2025 Regular delivery of bugfixes and improvements
2 parents 6e13440 + d089310 commit e885088

File tree

20 files changed

+2225
-1118
lines changed

20 files changed

+2225
-1118
lines changed

app/code/Magento/Catalog/Test/Mftf/Test/StorefrontAssertsCustomerBehaviourForProductTest.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1010
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
11-
<test name="StorefrontAssertsCustomerBehaviourForProductTest">
11+
<test name="StorefrontAssertsCustomerBehaviourForProductTest" deprecated="Use StorefrontSearchToolbarTest instead">
1212
<annotations>
1313
<features value="Catalog"/>
1414
<stories value="Product Sorting for guest/customer in storefront"/>
@@ -17,6 +17,9 @@
1717
<severity value="MAJOR"/>
1818
<testCaseId value="AC-8905"/>
1919
<group value="catalog"/>
20+
<skip>
21+
<issueId value="DEPRECATED">Use StorefrontSearchToolbarTest instead</issueId>
22+
</skip>
2023
</annotations>
2124
<before>
2225
<!-- Precondition Step.1: Magento should be installed.with Sample Data -->

app/code/Magento/CatalogSearch/Controller/Result/Index.php

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
use Magento\Store\Model\StoreManagerInterface;
1414
use Magento\Search\Model\QueryFactory;
1515
use Magento\Search\Model\PopularSearchTerms;
16+
use Magento\Catalog\Model\Product\ProductList\ToolbarMemorizer;
17+
use Magento\Catalog\Model\Product\ProductList\Toolbar;
1618

1719
/**
1820
* Search result.
@@ -22,10 +24,10 @@ class Index extends \Magento\Framework\App\Action\Action implements HttpGetActio
2224
/**
2325
* No results default handle.
2426
*/
25-
const DEFAULT_NO_RESULT_HANDLE = 'catalogsearch_result_index_noresults';
27+
public const DEFAULT_NO_RESULT_HANDLE = 'catalogsearch_result_index_noresults';
2628

2729
/**
28-
* Catalog session
30+
* Catalog session for storing catalog-related data
2931
*
3032
* @var Session
3133
*/
@@ -48,25 +50,34 @@ class Index extends \Magento\Framework\App\Action\Action implements HttpGetActio
4850
*/
4951
private $layerResolver;
5052

53+
/**
54+
* @var ToolbarMemorizer
55+
*/
56+
private $toolbarMemorizer;
57+
5158
/**
5259
* @param Context $context
5360
* @param Session $catalogSession
5461
* @param StoreManagerInterface $storeManager
5562
* @param QueryFactory $queryFactory
5663
* @param Resolver $layerResolver
64+
* @param ToolbarMemorizer|null $toolbarMemorizer
5765
*/
5866
public function __construct(
5967
Context $context,
6068
Session $catalogSession,
6169
StoreManagerInterface $storeManager,
6270
QueryFactory $queryFactory,
63-
Resolver $layerResolver
71+
Resolver $layerResolver,
72+
?ToolbarMemorizer $toolbarMemorizer = null
6473
) {
6574
parent::__construct($context);
6675
$this->_storeManager = $storeManager;
6776
$this->_catalogSession = $catalogSession;
6877
$this->_queryFactory = $queryFactory;
6978
$this->layerResolver = $layerResolver;
79+
$this->toolbarMemorizer = $toolbarMemorizer ?:
80+
\Magento\Framework\App\ObjectManager::getInstance()->get(ToolbarMemorizer::class);
7081
}
7182

7283
/**
@@ -101,6 +112,11 @@ public function execute()
101112
$handles[] = static::DEFAULT_NO_RESULT_HANDLE;
102113
}
103114

115+
if ($this->shouldRedirectOnToolbarAction()) {
116+
$this->getResponse()->setRedirect($this->_redirect->getRedirectUrl());
117+
return;
118+
}
119+
104120
if (empty($getAdditionalRequestParameters) &&
105121
$this->_objectManager->get(PopularSearchTerms::class)->isCacheable($queryText, $storeId)
106122
) {
@@ -166,4 +182,21 @@ private function getNotCacheableResult($catalogSearchHelper, $query, $handles)
166182
$this->getResponse()->setNoCacheHeaders();
167183
$this->_view->renderLayout();
168184
}
185+
186+
/**
187+
* Checks for toolbar actions
188+
*
189+
* @return bool
190+
*/
191+
private function shouldRedirectOnToolbarAction(): bool
192+
{
193+
$params = $this->getRequest()->getParams();
194+
195+
return $this->toolbarMemorizer->isMemorizingAllowed() && empty(array_intersect([
196+
Toolbar::ORDER_PARAM_NAME,
197+
Toolbar::DIRECTION_PARAM_NAME,
198+
Toolbar::MODE_PARAM_NAME,
199+
Toolbar::LIMIT_PARAM_NAME
200+
], array_keys($params))) === false;
201+
}
169202
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright 2025 Adobe
5+
* All Rights Reserved.
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="StorefrontSearchSetDefaultDisplaySettingsActionGroup">
12+
<annotations>
13+
<description>Sets search display to default settings: grid mode, relevance descending, 12 items per page. Fails if not on search results page.</description>
14+
</annotations>
15+
16+
<!-- Check if we're on the search results page -->
17+
<seeInCurrentUrl url="{{StorefrontCatalogSearchPage.url}}" stepKey="verifyOnSearchPage"/>
18+
19+
<!-- Set display mode to grid (default) -->
20+
<click selector="{{StorefrontSearchTopToolbarSection.gridMode}}" stepKey="selectGridMode"/>
21+
<waitForPageLoad stepKey="waitForGridModeApplied"/>
22+
23+
<!-- Set sort field to relevance (default for search) -->
24+
<selectOption selector="{{StorefrontSearchTopToolbarSection.sortByDropdown}}" userInput="relevance" stepKey="selectSortByRelevance"/>
25+
<waitForPageLoad stepKey="waitForRelevanceSortingApplied"/>
26+
27+
<!-- If currently ascending, click to change to descending -->
28+
<conditionalClick
29+
selector="{{StorefrontSearchTopToolbarSection.sortDirectionAsc}}"
30+
dependentSelector="{{StorefrontSearchTopToolbarSection.sortDirectionAsc}}"
31+
visible="true"
32+
stepKey="clickAscendingIfVisible"/>
33+
34+
<!-- Set items per page to 12 (default) -->
35+
<selectOption selector="{{StorefrontSearchTopToolbarSection.showDropdown}}" userInput="12" stepKey="selectItemsPerPage12"/>
36+
<waitForPageLoad stepKey="waitForSettingsApplied"/>
37+
38+
<!-- Verify all default settings are properly applied -->
39+
<seeElement selector="{{StorefrontSearchTopToolbarSection.gridMode}}" stepKey="verifyGridModeSelected"/>
40+
<seeOptionIsSelected selector="{{StorefrontSearchTopToolbarSection.sortByDropdown}}" userInput="relevance" stepKey="verifyRelevanceSortSelected"/>
41+
<seeElement selector="{{StorefrontSearchTopToolbarSection.sortDirectionDesc}}" stepKey="verifyDescendingSortDirection"/>
42+
<seeOptionIsSelected selector="{{StorefrontSearchTopToolbarSection.showDropdown}}" userInput="12" stepKey="verify12ItemsPerPageSelected"/>
43+
</actionGroup>
44+
</actionGroups>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright 2025 Adobe
5+
* All Rights Reserved.
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="StorefrontSearchTopToolbarSection">
12+
<element name="searchResultsToolbar" type="block" selector=".toolbar.toolbar-products" timeout="30"/>
13+
<element name="gridMode" type="button" selector=".toolbar.toolbar-products .modes .mode-grid" timeout="30"/>
14+
<element name="listMode" type="button" selector=".toolbar.toolbar-products .modes .mode-list" timeout="30"/>
15+
<element name="sortByDropdown" type="select" selector=".toolbar.toolbar-products .sorter #sorter" timeout="30"/>
16+
<element name="sortDirectionAsc" type="button" selector=".toolbar.toolbar-products .sorter a.sort-asc" timeout="30"/>
17+
<element name="sortDirectionDesc" type="button" selector=".toolbar.toolbar-products .sorter a.sort-desc" timeout="30"/>
18+
<element name="showDropdown" type="select" selector=".toolbar.toolbar-products .limiter #limiter" timeout="30"/>
19+
</section>
20+
</sections>
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright 2025 Adobe
5+
* All Rights Reserved.
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="StorefrontSearchToolbarTest">
12+
<annotations>
13+
<features value="Search"/>
14+
<stories value="Search Result Toolbar"/>
15+
<title value="Verify sorting toolbar changes on search results work as expected and don't cause form resubmission dialog"/>
16+
<description value="Test that sorting toolbar changes apply properly and redirect properly to prevent 'Confirm Form Resubmission' dialog when using back button, and toolbar settings are preserved"/>
17+
<severity value="MAJOR"/>
18+
<testCaseId value="AC-15666,AC-8905"/>
19+
<useCaseId value="ACP2E-4208"/>
20+
<group value="CatalogSearch"/>
21+
</annotations>
22+
23+
<before>
24+
<!-- Create several products to have enough for pagination/sorting -->
25+
<createData entity="SimpleProduct" stepKey="createProduct1">
26+
<field key="name">StorefrontSearchToolbarTestProduct C</field>
27+
<field key="price">30.00</field>
28+
</createData>
29+
<createData entity="SimpleProduct" stepKey="createProduct2">
30+
<field key="name">StorefrontSearchToolbarTestProduct B</field>
31+
<field key="price">10.00</field>
32+
</createData>
33+
<createData entity="SimpleProduct" stepKey="createProduct3">
34+
<field key="name">StorefrontSearchToolbarTestProduct A</field>
35+
<field key="price">20.00</field>
36+
</createData>
37+
38+
<!-- Enable remember pagination -->
39+
<createData entity="RememberPaginationCatalogStorefrontConfig" stepKey="setRememberPaginationCatalogStorefrontConfig"/>
40+
</before>
41+
42+
<after>
43+
<!-- Reset display settings to default -->
44+
<actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchForProductsCleanup">
45+
<argument name="phrase" value="StorefrontSearchToolbarTestProduct"/>
46+
</actionGroup>
47+
<actionGroup ref="StorefrontSearchSetDefaultDisplaySettingsActionGroup" stepKey="resetDisplaySettingsToDefault"/>
48+
49+
<!-- Clean up products and category -->
50+
<deleteData createDataKey="createProduct1" stepKey="deleteProduct1"/>
51+
<deleteData createDataKey="createProduct2" stepKey="deleteProduct2"/>
52+
<deleteData createDataKey="createProduct3" stepKey="deleteProduct3"/>
53+
54+
<!-- Reset configuration -->
55+
<createData entity="DefaultCatalogStorefrontConfiguration" stepKey="setDefaultCatalogStorefrontConfiguration"/>
56+
</after>
57+
58+
<!-- Step 1: Navigate to storefront and perform initial search -->
59+
<actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="goToStorefront"/>
60+
<actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchForProducts">
61+
<argument name="phrase" value="StorefrontSearchToolbarTestProduct"/>
62+
</actionGroup>
63+
64+
<!-- Set default search display settings once at the beginning -->
65+
<actionGroup ref="StorefrontSearchSetDefaultDisplaySettingsActionGroup" stepKey="setSearchDisplayDefaultSettings"/>
66+
67+
<!-- Step 2: Change sort order to price, then to name -->
68+
<selectOption selector="{{StorefrontSearchTopToolbarSection.sortByDropdown}}" userInput="price" stepKey="selectSortByPrice"/>
69+
<waitForPageLoad stepKey="waitForPriceSortingApplied"/>
70+
71+
<!-- Change to ascending price order -->
72+
<click selector="{{StorefrontSearchTopToolbarSection.sortDirectionDesc}}" stepKey="changePriceToAscending"/>
73+
<waitForPageLoad stepKey="waitForAscendingPriceApplied"/>
74+
75+
<!-- Verify Product B is displayed first (lowest price $10.00) -->
76+
<see userInput="StorefrontSearchToolbarTestProduct B" selector="{{StorefrontCategoryMainSection.productNameByPosition('1')}}" stepKey="seeProductBFirstByPrice"/>
77+
78+
<!-- Now change sort to name -->
79+
<selectOption selector="{{StorefrontSearchTopToolbarSection.sortByDropdown}}" userInput="name" stepKey="selectSortByName"/>
80+
<waitForPageLoad stepKey="waitForNameSortingApplied"/>
81+
82+
<!-- Verify Product A is displayed first (alphabetically first in ascending order) -->
83+
<see userInput="StorefrontSearchToolbarTestProduct A" selector="{{StorefrontCategoryMainSection.productNameByPosition('1')}}" stepKey="seeProductAFirstByName"/>
84+
85+
<!-- Step 3: Change sort direction to descending -->
86+
<click selector="{{StorefrontSearchTopToolbarSection.sortDirectionAsc}}" stepKey="changeSortToDescending"/>
87+
<waitForPageLoad stepKey="waitForDescendingSortingApplied"/>
88+
89+
<!-- Verify Product C is displayed first (alphabetically last in descending order) -->
90+
<see userInput="StorefrontSearchToolbarTestProduct C" selector="{{StorefrontCategoryMainSection.productNameByPosition('1')}}" stepKey="seeProductCFirstByNameDesc"/>
91+
92+
<!-- Change items per page -->
93+
<selectOption selector="{{StorefrontSearchTopToolbarSection.showDropdown}}" userInput="24" stepKey="selectItemsPerPage"/>
94+
<waitForPageLoad stepKey="waitForLimitApplied"/>
95+
96+
<!-- Step 4: Navigate to a product page -->
97+
<comment userInput="Navigate to product page to test back button behavior" stepKey="commentNavigateToProduct"/>
98+
<click selector="{{StorefrontCategoryMainSection.specifiedProductItemInfo('StorefrontSearchToolbarTestProduct C')}}" stepKey="clickOnFirstProduct"/>
99+
<waitForPageLoad stepKey="waitForProductPage"/>
100+
101+
<!-- Verify we're on Product C page -->
102+
<see userInput="StorefrontSearchToolbarTestProduct C" selector="{{StorefrontProductInfoMainSection.productName}}" stepKey="seeProductCName"/>
103+
<seeInCurrentUrl url=".html" stepKey="seeProductUrl"/>
104+
105+
<!-- Step 5: Use back button to return to search results -->
106+
<moveBack stepKey="clickBackButton"/>
107+
<waitForPageLoad stepKey="waitForBackNavigation"/>
108+
109+
<!-- Step 6: Verify we're back on search page -->
110+
<comment userInput="Verify search results page is displayed and toolbar settings are preserved" stepKey="commentVerifySearchPage"/>
111+
<see userInput="Search results for: 'StorefrontSearchToolbarTestProduct'" stepKey="seeSearchResultsTitleAfterBack"/>
112+
<seeInCurrentUrl url="catalogsearch/result" stepKey="seeSearchUrlAfterBack"/>
113+
114+
<!-- Step 7: "Verify all display settings are preserved -->
115+
<comment userInput="Verify all display settings are preserved: grid mode, name sort descending, 24 items per page" stepKey="commentVerifyAllSettings"/>
116+
<seeElement selector="{{StorefrontSearchTopToolbarSection.gridMode}}" stepKey="verifyGridModePreserved"/>
117+
<seeOptionIsSelected selector="{{StorefrontSearchTopToolbarSection.sortByDropdown}}" userInput="name" stepKey="verifyNameSortPreserved"/>
118+
<seeElement selector="{{StorefrontSearchTopToolbarSection.sortDirectionDesc}}" stepKey="verifyDescendingSortPreserved"/>
119+
<seeOptionIsSelected selector="{{StorefrontSearchTopToolbarSection.showDropdown}}" userInput="24" stepKey="verify24ItemsPerPagePreserved"/>
120+
121+
<!-- Product order matches expectations (C-B-A descending by name) -->
122+
<see userInput="StorefrontSearchToolbarTestProduct C" selector="{{StorefrontCategoryMainSection.productNameByPosition('1')}}" stepKey="finalVerifyProductCFirst"/>
123+
<see userInput="StorefrontSearchToolbarTestProduct B" selector="{{StorefrontCategoryMainSection.productNameByPosition('2')}}" stepKey="finalVerifyProductBSecond"/>
124+
<see userInput="StorefrontSearchToolbarTestProduct A" selector="{{StorefrontCategoryMainSection.productNameByPosition('3')}}" stepKey="finalVerifyProductAThird"/>
125+
126+
<!-- Step 8: Verify sorting functionality still works after back button navigation -->
127+
<comment userInput="Test that sorting functionality is still operational after back button navigation" stepKey="commentTestSortingStillWorks"/>
128+
129+
<!-- Change sort direction to ascending to test sorting still works -->
130+
<click selector="{{StorefrontSearchTopToolbarSection.sortDirectionDesc}}" stepKey="changeSortToAscendingAfterBack"/>
131+
<waitForPageLoad stepKey="waitForAscendingSortingAfterBack"/>
132+
133+
<!-- Verify Product A is now first (alphabetically first in ascending order) -->
134+
<see userInput="StorefrontSearchToolbarTestProduct A" selector="{{StorefrontCategoryMainSection.productNameByPosition('1')}}" stepKey="verifyProductAFirstAfterSortChange"/>
135+
136+
<!-- Change sort back to price to test different sorting option -->
137+
<selectOption selector="{{StorefrontSearchTopToolbarSection.sortByDropdown}}" userInput="price" stepKey="selectSortByPriceAfterBack"/>
138+
<waitForPageLoad stepKey="waitForPriceSortingAfterBack"/>
139+
140+
<!-- Verify Product B is first (lowest price $10.00) -->
141+
<see userInput="StorefrontSearchToolbarTestProduct B" selector="{{StorefrontCategoryMainSection.productNameByPosition('1')}}" stepKey="verifyProductBFirstByPriceAfterBack"/>
142+
</test>
143+
</tests>

app/code/Magento/Checkout/Controller/Cart/UpdatePost.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ protected function _updateShoppingCart()
8484
}
8585
} catch (\Magento\Framework\Exception\LocalizedException $e) {
8686
$this->cart->save();
87-
$this->messageManager->addErrorMessage(
88-
$this->_objectManager->get(\Magento\Framework\Escaper::class)->escapeHtml($e->getMessage())
89-
);
87+
// We do not add an error message to messageManager here to prevent duplicate error messages
88+
// on the cart page. The frontend AJAX validation already displays this error, and the backend message
89+
// would cause duplication after page reload.
9090
} catch (\Exception $e) {
9191
$this->messageManager->addExceptionMessage($e, __('We can\'t update the shopping cart.'));
9292
$this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e);

0 commit comments

Comments
 (0)