Skip to content

Commit c1ccaa0

Browse files
committed
ACP2E-4208: "Confirm Form Resubmission" on Catalog Search with "Remember Category Pagination"
1 parent 6cda09a commit c1ccaa0

File tree

4 files changed

+256
-3
lines changed

4 files changed

+256
-3
lines changed

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: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* ADOBE CONFIDENTIAL
5+
*
6+
* Copyright 2025 Adobe
7+
* All Rights Reserved.
8+
*
9+
* NOTICE: All information contained herein is, and remains
10+
* the property of Adobe and its suppliers, if any. The intellectual
11+
* and technical concepts contained herein are proprietary to Adobe
12+
* and its suppliers and are protected by all applicable intellectual
13+
* property laws, including trade secret and copyright laws.
14+
* Dissemination of this information or reproduction of this material
15+
* is strictly forbidden unless prior written permission is obtained
16+
* from Adobe.
17+
*/
18+
-->
19+
20+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
21+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
22+
<actionGroup name="StorefrontSearchSetDefaultDisplaySettingsActionGroup">
23+
<annotations>
24+
<description>Sets search display to default settings: grid mode, relevance descending, 12 items per page</description>
25+
</annotations>
26+
27+
<!-- Set display mode to grid (default) -->
28+
<click selector="{{StorefrontSearchTopToolbarSection.gridMode}}" stepKey="selectGridMode"/>
29+
<waitForPageLoad stepKey="waitForGridModeApplied"/>
30+
31+
<!-- Set sort field to relevance (default for search) -->
32+
<selectOption selector="{{StorefrontSearchTopToolbarSection.sortByDropdown}}" userInput="relevance" stepKey="selectSortByRelevance"/>
33+
<waitForPageLoad stepKey="waitForRelevanceSortingApplied"/>
34+
35+
<!-- If currently ascending, click to change to descending -->
36+
<conditionalClick
37+
selector="{{StorefrontSearchTopToolbarSection.sortDirectionAsc}}"
38+
dependentSelector="{{StorefrontSearchTopToolbarSection.sortDirectionAsc}}"
39+
visible="true"
40+
stepKey="clickAscendingIfVisible"/>
41+
42+
<!-- Set items per page to 12 (default) -->
43+
<selectOption selector="{{StorefrontSearchTopToolbarSection.showDropdown}}" userInput="12" stepKey="selectItemsPerPage12"/>
44+
<waitForPageLoad stepKey="waitForSettingsApplied"/>
45+
46+
<!-- Verify all default settings are properly applied -->
47+
<seeElement selector="{{StorefrontSearchTopToolbarSection.gridMode}}" stepKey="verifyGridModeSelected"/>
48+
<seeOptionIsSelected selector="{{StorefrontSearchTopToolbarSection.sortByDropdown}}" userInput="relevance" stepKey="verifyRelevanceSortSelected"/>
49+
<seeElement selector="{{StorefrontSearchTopToolbarSection.sortDirectionDesc}}" stepKey="verifyDescendingSortDirection"/>
50+
<seeOptionIsSelected selector="{{StorefrontSearchTopToolbarSection.showDropdown}}" userInput="12" stepKey="verify12ItemsPerPageSelected"/>
51+
</actionGroup>
52+
</actionGroups>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* ADOBE CONFIDENTIAL
5+
*
6+
* Copyright 2025 Adobe
7+
* All Rights Reserved.
8+
*
9+
* NOTICE: All information contained herein is, and remains
10+
* the property of Adobe and its suppliers, if any. The intellectual
11+
* and technical concepts contained herein are proprietary to Adobe
12+
* and its suppliers and are protected by all applicable intellectual
13+
* property laws, including trade secret and copyright laws.
14+
* Dissemination of this information or reproduction of this material
15+
* is strictly forbidden unless prior written permission is obtained
16+
* from Adobe.
17+
*/
18+
-->
19+
20+
<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
21+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
22+
<section name="StorefrontSearchTopToolbarSection">
23+
<element name="searchResultsToolbar" type="block" selector=".toolbar.toolbar-products" timeout="30"/>
24+
<element name="gridMode" type="button" selector=".//*[@class='toolbar toolbar-products'][1]//*[@data-value='grid']" timeout="30"/>
25+
<element name="listMode" type="button" selector=".//*[@class='toolbar toolbar-products'][1]//*[@data-value='list']" timeout="30"/>
26+
<element name="sortByDropdown" type="select" selector=".catalogsearch-result-index .toolbar-products #sorter" timeout="30"/>
27+
<element name="sortDirectionAsc" type="button" selector=".//*[@class='toolbar toolbar-products'][1]//a[contains(@class, 'sort-asc')]" timeout="30"/>
28+
<element name="sortDirectionDesc" type="button" selector=".//*[@class='toolbar toolbar-products'][1]//a[contains(@class, 'sort-desc')]" timeout="30"/>
29+
<element name="showDropdown" type="select" selector=".catalogsearch-result-index .toolbar-products #limiter" timeout="30"/>
30+
</section>
31+
</sections>
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* ADOBE CONFIDENTIAL
5+
*
6+
* Copyright 2025 Adobe
7+
* All Rights Reserved.
8+
*
9+
* NOTICE: All information contained herein is, and remains
10+
* the property of Adobe and its suppliers, if any. The intellectual
11+
* and technical concepts contained herein are proprietary to Adobe
12+
* and its suppliers and are protected by all applicable intellectual
13+
* property laws, including trade secret and copyright laws.
14+
* Dissemination of this information or reproduction of this material
15+
* is strictly forbidden unless prior written permission is obtained
16+
* from Adobe.
17+
*/
18+
-->
19+
20+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
21+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
22+
<test name="StorefrontSearchToolbarTest">
23+
<annotations>
24+
<features value="Search"/>
25+
<stories value="Search Result Toolbar"/>
26+
<title value="Verify sorting toolbar changes on search results work as expected and don't cause form resubmission dialog"/>
27+
<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"/>
28+
<severity value="AVERAGE"/>
29+
<testCaseId value="AC-15666"/>
30+
<useCaseId value="ACP2E-4208"/>
31+
<group value="CatalogSearch"/>
32+
</annotations>
33+
34+
<before>
35+
<!-- Create several products to have enough for pagination/sorting -->
36+
<createData entity="SimpleProduct" stepKey="createProduct1">
37+
<field key="name">StorefrontSearchToolbarTestProduct C</field>
38+
<field key="price">30.00</field>
39+
</createData>
40+
<createData entity="SimpleProduct" stepKey="createProduct2">
41+
<field key="name">StorefrontSearchToolbarTestProduct B</field>
42+
<field key="price">10.00</field>
43+
</createData>
44+
<createData entity="SimpleProduct" stepKey="createProduct3">
45+
<field key="name">StorefrontSearchToolbarTestProduct A</field>
46+
<field key="price">20.00</field>
47+
</createData>
48+
49+
<!-- Enable remember pagination -->
50+
<createData entity="RememberPaginationCatalogStorefrontConfig" stepKey="setRememberPaginationCatalogStorefrontConfig"/>
51+
</before>
52+
53+
<after>
54+
<!-- Reset display settings to default -->
55+
<actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchForProductsCleanup">
56+
<argument name="phrase" value="StorefrontSearchToolbarTestProduct"/>
57+
</actionGroup>
58+
<actionGroup ref="StorefrontSearchSetDefaultDisplaySettingsActionGroup" stepKey="resetDisplaySettingsToDefault"/>
59+
60+
<!-- Clean up products and category -->
61+
<deleteData createDataKey="createProduct1" stepKey="deleteProduct1"/>
62+
<deleteData createDataKey="createProduct2" stepKey="deleteProduct2"/>
63+
<deleteData createDataKey="createProduct3" stepKey="deleteProduct3"/>
64+
65+
<!-- Reset configuration -->
66+
<createData entity="DefaultCatalogStorefrontConfiguration" stepKey="setDefaultCatalogStorefrontConfiguration"/>
67+
</after>
68+
69+
<!-- Step 1: Navigate to storefront and perform initial search -->
70+
<actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="goToStorefront"/>
71+
<actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchForProducts">
72+
<argument name="phrase" value="StorefrontSearchToolbarTestProduct"/>
73+
</actionGroup>
74+
75+
<!-- Set default search display settings once at the beginning -->
76+
<actionGroup ref="StorefrontSearchSetDefaultDisplaySettingsActionGroup" stepKey="setSearchDisplayDefaultSettings"/>
77+
78+
<!-- Step 2: Change sort order to price, then to name -->
79+
<selectOption selector="{{StorefrontSearchTopToolbarSection.sortByDropdown}}" userInput="price" stepKey="selectSortByPrice"/>
80+
<waitForPageLoad stepKey="waitForPriceSortingApplied"/>
81+
82+
<!-- Change to ascending price order -->
83+
<click selector="{{StorefrontSearchTopToolbarSection.sortDirectionDesc}}" stepKey="changePriceToAscending"/>
84+
<waitForPageLoad stepKey="waitForAscendingPriceApplied"/>
85+
86+
<!-- Verify Product B is displayed first (lowest price $10.00) -->
87+
<see userInput="StorefrontSearchToolbarTestProduct B" selector="{{StorefrontCategoryMainSection.productNameByPosition('1')}}" stepKey="seeProductBFirstByPrice"/>
88+
89+
<!-- Now change sort to name -->
90+
<selectOption selector="{{StorefrontSearchTopToolbarSection.sortByDropdown}}" userInput="name" stepKey="selectSortByName"/>
91+
<waitForPageLoad stepKey="waitForNameSortingApplied"/>
92+
93+
<!-- Verify Product A is displayed first (alphabetically first in ascending order) -->
94+
<see userInput="StorefrontSearchToolbarTestProduct A" selector="{{StorefrontCategoryMainSection.productNameByPosition('1')}}" stepKey="seeProductAFirstByName"/>
95+
96+
<!-- Step 3: Change sort direction to descending -->
97+
<click selector="{{StorefrontSearchTopToolbarSection.sortDirectionAsc}}" stepKey="changeSortToDescending"/>
98+
<waitForPageLoad stepKey="waitForDescendingSortingApplied"/>
99+
100+
<!-- Verify Product C is displayed first (alphabetically last in descending order) -->
101+
<see userInput="StorefrontSearchToolbarTestProduct C" selector="{{StorefrontCategoryMainSection.productNameByPosition('1')}}" stepKey="seeProductCFirstByNameDesc"/>
102+
103+
<!-- Change items per page -->
104+
<selectOption selector="{{StorefrontSearchTopToolbarSection.showDropdown}}" userInput="24" stepKey="selectItemsPerPage"/>
105+
<waitForPageLoad stepKey="waitForLimitApplied"/>
106+
107+
<!-- Step 4: Navigate to a product page -->
108+
<comment userInput="Navigate to product page to test back button behavior" stepKey="commentNavigateToProduct"/>
109+
<click selector="{{StorefrontCategoryMainSection.specifiedProductItemInfo('StorefrontSearchToolbarTestProduct C')}}" stepKey="clickOnFirstProduct"/>
110+
<waitForPageLoad stepKey="waitForProductPage"/>
111+
112+
<!-- Verify we're on Product C page -->
113+
<see userInput="StorefrontSearchToolbarTestProduct C" selector="{{StorefrontProductInfoMainSection.productName}}" stepKey="seeProductCName"/>
114+
<seeInCurrentUrl url=".html" stepKey="seeProductUrl"/>
115+
116+
<!-- Step 5: Use back button to return to search results -->
117+
<moveBack stepKey="clickBackButton"/>
118+
<waitForPageLoad stepKey="waitForBackNavigation"/>
119+
120+
<!-- Step 6: Verify we're back on search page -->
121+
<comment userInput="Verify search results page is displayed and toolbar settings are preserved" stepKey="commentVerifySearchPage"/>
122+
<see userInput="Search results for: 'StorefrontSearchToolbarTestProduct'" stepKey="seeSearchResultsTitleAfterBack"/>
123+
<seeInCurrentUrl url="catalogsearch/result" stepKey="seeSearchUrlAfterBack"/>
124+
125+
<!-- Step 7: "Verify all display settings are preserved -->
126+
<comment userInput="Verify all display settings are preserved: grid mode, name sort descending, 24 items per page" stepKey="commentVerifyAllSettings"/>
127+
<seeElement selector="{{StorefrontSearchTopToolbarSection.gridMode}}" stepKey="verifyGridModePreserved"/>
128+
<seeOptionIsSelected selector="{{StorefrontSearchTopToolbarSection.sortByDropdown}}" userInput="name" stepKey="verifyNameSortPreserved"/>
129+
<seeElement selector="{{StorefrontSearchTopToolbarSection.sortDirectionDesc}}" stepKey="verifyDescendingSortPreserved"/>
130+
<seeOptionIsSelected selector="{{StorefrontSearchTopToolbarSection.showDropdown}}" userInput="24" stepKey="verify24ItemsPerPagePreserved"/>
131+
132+
<!-- Product order matches expectations (C-B-A descending by name) -->
133+
<see userInput="StorefrontSearchToolbarTestProduct C" selector="{{StorefrontCategoryMainSection.productNameByPosition('1')}}" stepKey="finalVerifyProductCFirst"/>
134+
<see userInput="StorefrontSearchToolbarTestProduct B" selector="{{StorefrontCategoryMainSection.productNameByPosition('2')}}" stepKey="finalVerifyProductBSecond"/>
135+
<see userInput="StorefrontSearchToolbarTestProduct A" selector="{{StorefrontCategoryMainSection.productNameByPosition('3')}}" stepKey="finalVerifyProductAThird"/>
136+
</test>
137+
</tests>

0 commit comments

Comments
 (0)