Skip to content

Commit 0df8611

Browse files
MC-36965: Create automated test for "[ES] Search with Layered Navigation and different types of attribute products.
1 parent edfbc39 commit 0df8611

File tree

17 files changed

+685
-3
lines changed

17 files changed

+685
-3
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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="StorefrontAssertAppliedFilterActionGroup">
12+
<annotations>
13+
<description>Asserts applied filter label and value on category page is layered navigation block.</description>
14+
</annotations>
15+
<arguments>
16+
<argument name="attributeLabel" type="string" defaultValue=""/>
17+
<argument name="attributeOptionLabel" type="string" defaultValue=""/>
18+
</arguments>
19+
<see selector="{{StorefrontLayeredNavigationSection.appliedFilterLabel('1')}}" userInput="{{attributeLabel}}" stepKey="seeAppliedFilterLabel"/>
20+
<see selector="{{StorefrontLayeredNavigationSection.appliedFilterValue('1')}}" userInput="{{attributeOptionLabel}}" stepKey="seeAppliedFilterValue"/>
21+
</actionGroup>
22+
</actionGroups>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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="StorefrontFilterCategoryPageByAttributeOptionActionGroup">
12+
<annotations>
13+
<description>Filters category page by given filterable attribute and attribute option is layered navigation block.</description>
14+
</annotations>
15+
<arguments>
16+
<argument name="attributeLabel" type="string" defaultValue=""/>
17+
<argument name="attributeOptionLabel" type="string" defaultValue=""/>
18+
</arguments>
19+
<waitForElementVisible selector="{{StorefrontCategorySidebarSection.filterOptionsTitle(attributeLabel)}}" stepKey="waitForFilterVisible"/>
20+
<conditionalClick selector="{{StorefrontCategorySidebarSection.filterOptionsTitle(attributeLabel)}}" dependentSelector="{{StorefrontCategorySidebarSection.activeFilterOptions}}" visible="false" stepKey="clickToExpandFilter"/>
21+
<click selector="{{StorefrontCategorySidebarSection.enabledFilterOptionItemByLabel(attributeOptionLabel)}}" stepKey="clickOnOption"/>
22+
</actionGroup>
23+
</actionGroups>

app/code/Magento/LayeredNavigation/Test/Mftf/Section/LayeredNavigationSection/StorefrontLayeredNavigationSection.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,7 @@
99
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
1010
<section name="StorefrontLayeredNavigationSection">
1111
<element name="shoppingOptionsByName" type="button" selector="//*[text()='Shopping Options']/..//*[contains(text(),'{{arg}}')]" parameterized="true"/>
12+
<element name="appliedFilterLabel" type="text" selector=".filter-current .items > li.item:nth-of-type({{position}}) > span.filter-label" parameterized="true" timeout="30"/>
13+
<element name="appliedFilterValue" type="text" selector=".filter-current .items > li.item:nth-of-type({{position}}) > span.filter-value" parameterized="true" timeout="30"/>
1214
</section>
1315
</sections>
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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="StorefrontDropdownAttributeInLayeredNavigationTest">
12+
<annotations>
13+
<features value="LayeredNavigation"/>
14+
<stories value="Product attributes in Layered Navigation"/>
15+
<title value="[ES] Search with Layered Navigation and different types of attribute products."/>
16+
<description value="Filtering by dropdown attribute in Layered navigation"/>
17+
<severity value="CRITICAL"/>
18+
<testCaseId value="MC-28963"/>
19+
<group value="layeredNavigation"/>
20+
<group value="catalog"/>
21+
<group value="SearchEngineElasticsearch"/>
22+
</annotations>
23+
<before>
24+
<createData entity="SimpleSubCategory" stepKey="createCategory"/>
25+
<createData entity="dropdownProductAttribute" stepKey="createDropdownProductAttribute"/>
26+
<createData entity="productAttributeOption" stepKey="firstDropdownProductAttributeOption">
27+
<requiredEntity createDataKey="createDropdownProductAttribute"/>
28+
</createData>
29+
<createData entity="productAttributeOption" stepKey="secondDropdownProductAttributeOption">
30+
<requiredEntity createDataKey="createDropdownProductAttribute"/>
31+
</createData>
32+
<getData entity="ProductAttributeOptionGetter" index="1" stepKey="getFirstDropdownProductAttributeOption">
33+
<requiredEntity createDataKey="createDropdownProductAttribute"/>
34+
</getData>
35+
<getData entity="ProductAttributeOptionGetter" index="2" stepKey="getSecondDropdownProductAttributeOption">
36+
<requiredEntity createDataKey="createDropdownProductAttribute"/>
37+
</getData>
38+
<createData entity="AddToDefaultSet" stepKey="AddDropdownProductAttributeToAttributeSet">
39+
<requiredEntity createDataKey="createDropdownProductAttribute"/>
40+
</createData>
41+
<createData entity="ApiSimpleProductWithCategory" stepKey="createFirstProduct">
42+
<requiredEntity createDataKey="createDropdownProductAttribute"/>
43+
<requiredEntity createDataKey="getFirstDropdownProductAttributeOption"/>
44+
<requiredEntity createDataKey="createCategory"/>
45+
</createData>
46+
<createData entity="ApiSimpleProductWithCategory" stepKey="createSecondProduct">
47+
<requiredEntity createDataKey="createDropdownProductAttribute"/>
48+
<requiredEntity createDataKey="getSecondDropdownProductAttributeOption"/>
49+
<requiredEntity createDataKey="createCategory"/>
50+
</createData>
51+
</before>
52+
<after>
53+
<deleteData createDataKey="createCategory" stepKey="deleteCategory"/>
54+
<deleteData createDataKey="createFirstProduct" stepKey="deleteFirstProduct"/>
55+
<deleteData createDataKey="createSecondProduct" stepKey="deleteSecondProduct"/>
56+
<deleteData createDataKey="createDropdownProductAttribute" stepKey="deleteDropdownProductAttribute"/>
57+
</after>
58+
<actionGroup ref="StorefrontNavigateCategoryPageActionGroup" stepKey="openCategory">
59+
<argument name="category" value="$createCategory$"/>
60+
</actionGroup>
61+
<actionGroup ref="AssertStorefrontAttributeOptionPresentInLayeredNavigationActionGroup" stepKey="assertFirstAttributeOptionPresentInLayeredNavigation">
62+
<argument name="attributeLabel" value="$createDropdownProductAttribute.attribute[frontend_labels][0][label]$"/>
63+
<argument name="attributeOptionLabel" value="$getFirstDropdownProductAttributeOption.label$"/>
64+
<argument name="attributeOptionPosition" value="1"/>
65+
</actionGroup>
66+
<actionGroup ref="AssertStorefrontAttributeOptionPresentInLayeredNavigationActionGroup" stepKey="assertSecondAttributeOptionPresentInLayeredNavigation">
67+
<argument name="attributeLabel" value="$createDropdownProductAttribute.attribute[frontend_labels][0][label]$"/>
68+
<argument name="attributeOptionLabel" value="$getSecondDropdownProductAttributeOption.label$"/>
69+
<argument name="attributeOptionPosition" value="2"/>
70+
</actionGroup>
71+
<actionGroup ref="StorefrontFilterCategoryPageByAttributeOptionActionGroup" stepKey="filterCategoryByFirstOption">
72+
<argument name="attributeLabel" value="$createDropdownProductAttribute.attribute[frontend_labels][0][label]$"/>
73+
<argument name="attributeOptionLabel" value="$getFirstDropdownProductAttributeOption.label$"/>
74+
</actionGroup>
75+
<actionGroup ref="StorefrontAssertAppliedFilterActionGroup" stepKey="assertFilterByFirstOption">
76+
<argument name="attributeLabel" value="$createDropdownProductAttribute.attribute[frontend_labels][0][label]$"/>
77+
<argument name="attributeOptionLabel" value="$getFirstDropdownProductAttributeOption.label$"/>
78+
</actionGroup>
79+
<actionGroup ref="AssertStorefrontProductIsPresentOnCategoryPageActionGroup" stepKey="assertFirstProductOnCatalogPage">
80+
<argument name="productName" value="$createFirstProduct.name$"/>
81+
</actionGroup>
82+
<actionGroup ref="StorefrontCheckProductIsMissingInCategoryProductsPageActionGroup" stepKey="assertSecondProductIsMissingOnCatalogPage">
83+
<argument name="productName" value="$createSecondProduct.name$"/>
84+
</actionGroup>
85+
<click selector="{{StorefrontCategorySidebarSection.removeFilter}}" stepKey="removeSideBarFilter"/>
86+
<waitForPageLoad stepKey="waitForPageLoad"/>
87+
<actionGroup ref="StorefrontFilterCategoryPageByAttributeOptionActionGroup" stepKey="filterCategoryBySecondOption">
88+
<argument name="attributeLabel" value="$createDropdownProductAttribute.attribute[frontend_labels][0][label]$"/>
89+
<argument name="attributeOptionLabel" value="$getSecondDropdownProductAttributeOption.label$"/>
90+
</actionGroup>
91+
<actionGroup ref="StorefrontAssertAppliedFilterActionGroup" stepKey="assertFilterBySecondOption">
92+
<argument name="attributeLabel" value="$createDropdownProductAttribute.attribute[frontend_labels][0][label]$"/>
93+
<argument name="attributeOptionLabel" value="$getSecondDropdownProductAttributeOption.label$"/>
94+
</actionGroup>
95+
<actionGroup ref="AssertStorefrontProductIsPresentOnCategoryPageActionGroup" stepKey="assertSecondProductOnCatalogPage">
96+
<argument name="productName" value="$createSecondProduct.name$"/>
97+
</actionGroup>
98+
<actionGroup ref="StorefrontCheckProductIsMissingInCategoryProductsPageActionGroup" stepKey="assertFirstProductIsMissingOnCatalogPage">
99+
<argument name="productName" value="$createFirstProduct.name$"/>
100+
</actionGroup>
101+
</test>
102+
</tests>

dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/AbstractFiltersTest.php

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
use Magento\Framework\Search\Request\Config;
2222
use Magento\Framework\View\LayoutInterface;
2323
use Magento\LayeredNavigation\Block\Navigation;
24-
use Magento\LayeredNavigation\Block\Navigation\Search as SearchNavigationBlock;
2524
use Magento\LayeredNavigation\Block\Navigation\Category as CategoryNavigationBlock;
25+
use Magento\LayeredNavigation\Block\Navigation\Search as SearchNavigationBlock;
2626
use Magento\Search\Model\Search;
2727
use Magento\Store\Model\Store;
2828
use Magento\TestFramework\Helper\Bootstrap;
@@ -124,6 +124,38 @@ protected function getCategoryFiltersAndAssert(
124124
}
125125
}
126126

127+
/**
128+
* Tests getFilters method from navigation block layer state on category page.
129+
*
130+
* @param array $products
131+
* @param array $expectation
132+
* @param string $categoryName
133+
* @param string|null $filterValue
134+
* @param int $productsCount
135+
* @return void
136+
*/
137+
protected function getCategoryActiveFiltersAndAssert(
138+
array $products,
139+
array $expectation,
140+
string $categoryName,
141+
string $filterValue,
142+
int $productsCount
143+
): void {
144+
$this->updateAttribute(['is_filterable' => AbstractFilter::ATTRIBUTE_OPTIONS_ONLY_WITH_RESULTS]);
145+
$this->updateProducts($products, $this->getAttributeCode());
146+
$this->clearInstanceAndReindexSearch();
147+
$this->navigationBlock->getRequest()->setParams($this->getRequestParams($filterValue));
148+
$this->navigationBlock->getLayer()->setCurrentCategory(
149+
$this->loadCategory($categoryName, Store::DEFAULT_STORE_ID)
150+
);
151+
$this->navigationBlock->setLayout($this->layout);
152+
$activeFilters = $this->navigationBlock->getLayer()->getState()->getFilters();
153+
$this->assertCount(1, $activeFilters);
154+
$currentFilter = reset($activeFilters);
155+
$this->assertActiveFilter($expectation, $currentFilter);
156+
$this->assertEquals($productsCount, $this->navigationBlock->getLayer()->getProductCollection()->getSize());
157+
}
158+
127159
/**
128160
* Tests getFilters method from navigation block on search page.
129161
*
@@ -152,6 +184,37 @@ protected function getSearchFiltersAndAssert(
152184
}
153185
}
154186

187+
/**
188+
* Tests getFilters method from navigation block layer state on search page.
189+
*
190+
* @param array $products
191+
* @param array $expectation
192+
* @param string $filterValue
193+
* @param int $productsCount
194+
* @return void
195+
*/
196+
protected function getSearchActiveFiltersAndAssert(
197+
array $products,
198+
array $expectation,
199+
string $filterValue,
200+
int $productsCount
201+
): void {
202+
$this->updateAttribute(
203+
['is_filterable' => AbstractFilter::ATTRIBUTE_OPTIONS_ONLY_WITH_RESULTS, 'is_filterable_in_search' => 1]
204+
);
205+
$this->updateProducts($products, $this->getAttributeCode());
206+
$this->clearInstanceAndReindexSearch();
207+
$this->navigationBlock->getRequest()->setParams(
208+
array_merge($this->getRequestParams($filterValue), ['q' => $this->getSearchString()])
209+
);
210+
$this->navigationBlock->setLayout($this->layout);
211+
$activeFilters = $this->navigationBlock->getLayer()->getState()->getFilters();
212+
$this->assertCount(1, $activeFilters);
213+
$currentFilter = reset($activeFilters);
214+
$this->assertActiveFilter($expectation, $currentFilter);
215+
$this->assertEquals($productsCount, $this->navigationBlock->getLayer()->getProductCollection()->getSize());
216+
}
217+
155218
/**
156219
* Returns filter with specified attribute.
157220
*
@@ -303,4 +366,37 @@ protected function getSearchString(): string
303366
{
304367
return 'Simple Product';
305368
}
369+
370+
/**
371+
* Adds params for filtering.
372+
*
373+
* @param string $filterValue
374+
* @return array
375+
*/
376+
protected function getRequestParams(string $filterValue): array
377+
{
378+
$attribute = $this->attributeRepository->get($this->getAttributeCode());
379+
$filterValue = $attribute->usesSource()
380+
? $attribute->getSource()->getOptionId($filterValue)
381+
: $filterValue;
382+
383+
return [$this->getAttributeCode() => $filterValue];
384+
}
385+
386+
/**
387+
* Asserts active filter data.
388+
*
389+
* @param array $expectation
390+
* @param Item $currentFilter
391+
* @return void
392+
*/
393+
protected function assertActiveFilter(array $expectation, Item $currentFilter): void
394+
{
395+
$this->assertEquals($expectation['label'], $currentFilter->getData('label'));
396+
$this->assertEquals($expectation['count'], $currentFilter->getData('count'));
397+
$this->assertEquals(
398+
$this->getAttributeCode(),
399+
$currentFilter->getFilter()->getData('attribute_model')->getAttributeCode()
400+
);
401+
}
306402
}

dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/BooleanFilterTest.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,58 @@ public function getFiltersWithCustomAttributeDataProvider(): array
6969
];
7070
}
7171

72+
/**
73+
* @magentoDataFixture Magento/Catalog/_files/product_boolean_attribute.php
74+
* @magentoDataFixture Magento/Catalog/_files/category_with_different_price_products.php
75+
* @dataProvider getActiveFiltersWithCustomAttributeDataProvider
76+
* @param array $products
77+
* @param array $expectation
78+
* @param string $filterValue
79+
* @param int $productsCount
80+
* @return void
81+
*/
82+
public function testGetActiveFiltersWithCustomAttribute(
83+
array $products,
84+
array $expectation,
85+
string $filterValue,
86+
int $productsCount
87+
): void {
88+
$this->getCategoryActiveFiltersAndAssert($products, $expectation, 'Category 999', $filterValue, $productsCount);
89+
}
90+
91+
/**
92+
* @return array
93+
*/
94+
public function getActiveFiltersWithCustomAttributeDataProvider(): array
95+
{
96+
return [
97+
'selected_yes_option_in_all_products' => [
98+
'products_data' => ['simple1000' => 'Yes', 'simple1001' => 'Yes'],
99+
'expectation' => ['label' => 'Yes', 'count' => 0],
100+
'filter_value' => 'Yes',
101+
'products_count' => 2,
102+
],
103+
'selected_yes_option_in_one_product' => [
104+
'products_data' => ['simple1000' => 'Yes', 'simple1001' => 'No'],
105+
'expectation' => ['label' => 'Yes', 'count' => 0],
106+
'filter_value' => 'Yes',
107+
'products_count' => 1,
108+
],
109+
'selected_no_option_in_all_products' => [
110+
'products_data' => ['simple1000' => 'No', 'simple1001' => 'No'],
111+
'expectation' => ['label' => 'No', 'count' => 0],
112+
'filter_value' => 'No',
113+
'products_count' => 2,
114+
],
115+
'selected_no_option_in_one_product' => [
116+
'products_data' => ['simple1000' => 'Yes', 'simple1001' => 'No'],
117+
'expectation' => ['label' => 'No', 'count' => 0],
118+
'filter_value' => 'No',
119+
'products_count' => 1,
120+
],
121+
];
122+
}
123+
72124
/**
73125
* @inheritdoc
74126
*/

0 commit comments

Comments
 (0)