Skip to content

Commit 3dcdba7

Browse files
authored
Merge pull request magento#4909 from magento-obsessive-owls/PB-48
[Owls] PB-48: The order of product SKU is not respected if combined with category condition
2 parents e90ddc6 + ed4c4ab commit 3dcdba7

File tree

7 files changed

+164
-18
lines changed

7 files changed

+164
-18
lines changed

app/code/Magento/Catalog/Test/Mftf/ActionGroup/CheckProductsOrderActionGroup.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@
1313
<description>Goes to the Storefront. Validates that the 2 provided Products appear in the correct order.</description>
1414
</annotations>
1515
<arguments>
16+
<argument name="page" defaultValue="{{StorefrontHomePage.url}}" type="string"/>
1617
<argument name="product_1"/>
1718
<argument name="product_2"/>
1819
</arguments>
1920

20-
<amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToHomePage"/>
21+
<amOnPage url="{{page}}" stepKey="goToHomePage"/>
2122
<waitForPageLoad stepKey="waitForPageLoad5"/>
2223
<grabAttributeFrom selector="{{StorefrontCategoryProductSection.ProductImageByNumber('1')}}" userInput="alt" stepKey="grabFirstProductName1_1"/>
2324
<assertEquals expected="{{product_1.name}}" actual="($grabFirstProductName1_1)" message="notExpectedOrder" stepKey="compare1"/>

app/code/Magento/Cms/Test/Mftf/ActionGroup/DeleteImageFromStorageActionGroup.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818

1919
<waitForElementVisible selector="{{MediaGallerySection.imageOrImageCopy(Image.fileName, Image.extension)}}" stepKey="waitForInitialImages"/>
2020
<grabMultiple selector="{{MediaGallerySection.imageOrImageCopy(Image.fileName, Image.extension)}}" stepKey="initialImages"/>
21-
<click selector="{{MediaGallerySection.imageOrImageCopy(Image.fileName, Image.extension)}}" stepKey="selectImage"/>
21+
<waitForElementVisible selector="{{MediaGallerySection.lastImageOrImageCopy(Image.fileName, Image.extension)}}" stepKey="waitForLastImage"/>
22+
<click selector="{{MediaGallerySection.lastImageOrImageCopy(Image.fileName, Image.extension)}}" stepKey="selectImage"/>
2223
<waitForElementVisible selector="{{MediaGallerySection.DeleteSelectedBtn}}" stepKey="waitForDeleteBtn"/>
2324
<click selector="{{MediaGallerySection.DeleteSelectedBtn}}" stepKey="clickDeleteSelected"/>
2425
<waitForPageLoad stepKey="waitForPageLoad1"/>

app/code/Magento/Cms/Test/Mftf/ActionGroup/SelectImageFromMediaStorageActionGroup.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252

5353
<actionGroup name="attachImage">
5454
<annotations>
55-
<description>Uploads the provided Image to Media Gallery.</description>
55+
<description>Uploads the provided Image to Media Gallery.
56+
If you use this action group, you MUST add steps to delete the image in the "after" steps.</description>
5657
</annotations>
5758
<arguments>
5859
<argument name="Image"/>

app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
<element name="BrowseUploadImage" type="file" selector=".fileupload" />
4141
<element name="image" type="text" selector="//small[text()='{{var1}}']" parameterized="true"/>
4242
<element name="imageOrImageCopy" type="text" selector="//div[contains(@class,'media-gallery-modal')]//img[contains(@alt, '{{arg1}}.{{arg2}}')]|//img[contains(@alt,'{{arg1}}_') and contains(@alt,'.{{arg2}}')]" parameterized="true"/>
43+
<element name="lastImageOrImageCopy" type="text" selector="(//div[contains(@class,'media-gallery-modal')]//img[contains(@alt, '{{arg1}}.{{arg2}}')]|//img[contains(@alt,'{{arg1}}_') and contains(@alt,'.{{arg2}}')])[last()]" parameterized="true"/>
4344
<element name="imageSelected" type="text" selector="//small[text()='{{var1}}']/parent::*[@class='filecnt selected']" parameterized="true"/>
4445
<element name="ImageSource" type="input" selector=".mce-combobox.mce-abs-layout-item.mce-last.mce-has-open" />
4546
<element name="ImageDescription" type="input" selector=".mce-textbox.mce-abs-layout-item.mce-last" />
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
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="CheckOrderOfProdsInWidgetOnCMSPageTest">
12+
<annotations>
13+
<features value="Catalog"/>
14+
<stories value="Widgets"/>
15+
<title value="Checking order of products in a widget on a CMS page - SKU condition"/>
16+
<description value="Checking order of products in a widget on a CMS page - SKU condition"/>
17+
<severity value="CRITICAL"/>
18+
<testCaseId value="MC-13718"/>
19+
<useCaseId value="MC-5906"/>
20+
<group value="Catalog"/>
21+
</annotations>
22+
<before>
23+
<actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/>
24+
<actionGroup ref="EnabledWYSIWYG" stepKey="enableWYSIWYG"/>
25+
<actionGroup ref="SwitchToVersion4ActionGroup" stepKey="enableTinyMCE4"/>
26+
<waitForPageLoad stepKey="waitConfigToSave"/>
27+
<createData entity="ApiCategory" stepKey="createFirstCategory"/>
28+
<createData entity="ApiSimpleProduct" stepKey="product1">
29+
<requiredEntity createDataKey="createFirstCategory"/>
30+
</createData>
31+
<createData entity="ApiSimpleProduct" stepKey="product2">
32+
<requiredEntity createDataKey="createFirstCategory"/>
33+
</createData>
34+
<createData entity="_defaultCmsPage" stepKey="createCMSPage"/>
35+
</before>
36+
<after>
37+
<actionGroup ref="DisabledWYSIWYG" stepKey="disableWYSIWYG"/>
38+
<deleteData createDataKey="createFirstCategory" stepKey="deleteCategory"/>
39+
<deleteData createDataKey="product1" stepKey="deleteProduct1"/>
40+
<deleteData createDataKey="product2" stepKey="deleteProduct2"/>
41+
<deleteData createDataKey="createCMSPage" stepKey="deletePreReqCMSPage"/>
42+
<actionGroup ref="logout" stepKey="logoutOfAdmin"/>
43+
</after>
44+
<actionGroup ref="navigateToCreatedCMSPage" stepKey="navigateToCreatedCMSPage1">
45+
<argument name="CMSPage" value="$$createCMSPage$$"/>
46+
</actionGroup>
47+
<conditionalClick selector="{{CmsNewPagePageContentSection.header}}"
48+
dependentSelector="{{CmsNewPagePageContentSection.header}}._show" visible="false"
49+
stepKey="clickContentTab1"/>
50+
<waitForPageLoad stepKey="waitForContentSectionLoad1"/>
51+
<waitForElementNotVisible selector="{{CmsWYSIWYGSection.CheckIfTabExpand}}" stepKey="waitForTabExpand1"/>
52+
<click selector="{{CmsNewPagePageActionsSection.showHideEditor}}" stepKey="showHiddenButtons"/>
53+
<seeElement selector="{{TinyMCESection.InsertWidgetBtn}}" stepKey="seeWidgetButton"/>
54+
<click selector="{{TinyMCESection.InsertWidgetBtn}}" stepKey="clickInsertWidgetButton"/>
55+
<waitForPageLoad stepKey="waitForPageLoad1"/>
56+
<see userInput="Inserting a widget does not create a widget instance." stepKey="seeMessage"/>
57+
<see selector="{{WidgetSection.InsertWidgetBtnDisabled}}" userInput="Insert Widget"
58+
stepKey="seeInsertWidgetDisabled"/>
59+
<see selector="{{WidgetSection.CancelBtnEnabled}}" userInput="Cancel" stepKey="seeCancelBtnEnabled"/>
60+
<selectOption selector="{{WidgetSection.WidgetType}}" userInput="Catalog Products List"
61+
stepKey="selectCatalogProductsList"/>
62+
<waitForPageLoad stepKey="waitBeforeClickingOnAddParamBtn"/>
63+
<click selector="{{WidgetSection.AddParam}}" stepKey="clickAddParamBtn"/>
64+
<waitForElement selector="{{WidgetSection.ConditionsDropdown}}" stepKey="addingWaitForConditionsDropDown"/>
65+
<waitForElementVisible selector="{{WidgetSection.ConditionsDropdown}}" stepKey="waitForDropdownVisible"/>
66+
<selectOption selector="{{WidgetSection.ConditionsDropdown}}" userInput="SKU"
67+
stepKey="selectCategoryCondition"/>
68+
<waitForPageLoad stepKey="waitBeforeClickingOnRuleParam"/>
69+
<click selector="{{WidgetSection.RuleParam1('3')}}" stepKey="clickOnRuleParam1"/>
70+
<waitForElementVisible selector="{{WidgetSection.RuleParamSelect('1','1')}}"
71+
stepKey="waitDropdownToAppear"/>
72+
<selectOption selector="{{WidgetSection.RuleParamSelect('1','1')}}" userInput="is one of"
73+
stepKey="selectOption"/>
74+
<waitForElement selector="{{WidgetSection.RuleParam}}" stepKey="waitForRuleParam"/>
75+
<click selector="{{WidgetSection.RuleParam}}" stepKey="clickOnRuleParam"/>
76+
<waitForElementVisible selector="{{WidgetSection.Chooser}}" stepKey="waitForElement"/>
77+
<click selector="{{WidgetSection.Chooser}}" stepKey="clickChooser"/>
78+
<waitForPageLoad stepKey="waitForPageToLoad"/>
79+
<fillField selector="{{WidgetSection.ChooserName}}" userInput="$$product1.name$$"
80+
stepKey="fillProduct1Name"/>
81+
<waitForPageLoad stepKey="waitForPageToLoadBeforeClickingOnSearchFilter1"/>
82+
<click selector="{{AdminNewWidgetSection.searchBlock}}" stepKey="searchFilter1"/>
83+
<waitForPageLoad stepKey="waitForPageToLoadBeforeSelectingProduct"/>
84+
<click selector="{{WidgetSection.PreCreateProduct('$$product1.name$$')}}" stepKey="selectProduct1"/>
85+
<click selector="{{AdminWidgetsSection.resetFilter}}" stepKey="resetFilter1"/>
86+
<waitForPageLoad stepKey="waitForPageToLoadBeforeFillingProductName"/>
87+
<fillField selector="{{WidgetSection.ChooserName}}" userInput="$$product2.name$$"
88+
stepKey="fillProduct2Name"/>
89+
<click selector="{{AdminNewWidgetSection.searchBlock}}" stepKey="clickOnSearch"/>
90+
<waitForPageLoad stepKey="waitForPageToLoadBeforeSelectingProduct2"/>
91+
<click selector="{{WidgetSection.PreCreateProduct('$$product2.name$$')}}" stepKey="selectProduct2"/>
92+
<click selector="{{AdminNewWidgetSection.applyParameter}}" stepKey="applyProducts"/>
93+
<click selector="{{WidgetSection.InsertWidget}}" stepKey="clickOnInsertWidgetButton"/>
94+
<waitForPageLoad stepKey="waitForPageToLoadBeforeClickingOnSaveWidget1"/>
95+
<click selector="{{InsertWidgetSection.save}}" stepKey="saveWidget"/>
96+
<waitForPageLoad stepKey="waitForSaveComplete"/>
97+
<actionGroup ref="CompareTwoProductsOrder" stepKey="compareProductOrders1">
98+
<argument name="page" value="$$createCMSPage.identifier$$"/>
99+
<argument name="product_1" value="$$product1$$"/>
100+
<argument name="product_2" value="$$product2$$"/>
101+
</actionGroup>
102+
<actionGroup ref="navigateToCreatedCMSPage" stepKey="navigateToCreatedCMSPage2">
103+
<argument name="CMSPage" value="$$createCMSPage$$"/>
104+
</actionGroup>
105+
<conditionalClick selector="{{CmsNewPagePageContentSection.header}}"
106+
dependentSelector="{{CmsNewPagePageContentSection.header}}._show" visible="false"
107+
stepKey="clickContentTab2"/>
108+
<waitForPageLoad stepKey="waitForContentSectionLoad2"/>
109+
<waitForElementNotVisible selector="{{CmsWYSIWYGSection.CheckIfTabExpand}}" stepKey="waitForTabExpand2"/>
110+
<executeJS function="jQuery('[id=\'cms_page_form_content_ifr\']').attr('name', 'preview-iframe')"
111+
stepKey="setPreviewFrameName"/>
112+
<switchToIFrame selector="preview-iframe" stepKey="switchToIframe"/>
113+
<doubleClick selector="{{TinyMCESection.WidgetButton}}" stepKey="clickToEditWidget"/>
114+
<switchToIFrame stepKey="switchOutFromIframe"/>
115+
<waitForPageLoad stepKey="waitForPageToLoadBeforeOpeningProductsList"/>
116+
<click selector="{{WidgetSection.RuleParam1('4')}}" stepKey="openProductsList"/>
117+
<waitForElementVisible selector="{{WidgetSection.Chooser}}" stepKey="waitForElement2"/>
118+
<click selector="{{WidgetSection.Chooser}}" stepKey="clickChooser2"/>
119+
<waitForPageLoad stepKey="waitForPageToLoadBeforeFillingProduct1Name"/>
120+
<fillField selector="{{WidgetSection.ChooserName}}" userInput="$$product1.name$$" stepKey="fillProduct1Name_2"/>
121+
<waitForPageLoad stepKey="waitForPageToLoadBeforeClickingOnSearchFilter2"/>
122+
<click selector="{{AdminNewWidgetSection.searchBlock}}" stepKey="searchFilter2"/>
123+
<waitForPageLoad stepKey="waitForPageToLoadBeforeSelectingProduct1"/>
124+
<click selector="{{WidgetSection.PreCreateProduct('$$product1.name$$')}}" stepKey="selectProduct1_1"/>
125+
<click selector="{{WidgetSection.PreCreateProduct('$$product1.name$$')}}" stepKey="selectProduct2_2"/>
126+
<click selector="{{AdminNewWidgetSection.applyParameter}}" stepKey="applyProducts1"/>
127+
<click selector="{{WidgetSection.InsertWidget}}" stepKey="clickOnInsertWidgetButton1"/>
128+
<waitForPageLoad stepKey="waitForPageToLoadBeforeClickingOnSaveWidget2"/>
129+
<click selector="{{InsertWidgetSection.save}}" stepKey="saveWidget1"/>
130+
<waitForPageLoad stepKey="waitForSaveComplete1"/>
131+
132+
<actionGroup ref="CompareTwoProductsOrder" stepKey="compareProductOrders2">
133+
<argument name="page" value="$$createCMSPage.identifier$$"/>
134+
<argument name="product_1" value="$$product2$$"/>
135+
<argument name="product_2" value="$$product1$$"/>
136+
</actionGroup>
137+
</test>
138+
</tests>

app/code/Magento/Rule/Model/Condition/Sql/Builder.php

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -270,25 +270,22 @@ private function buildConditions(AbstractCollection $collection, Combine $combin
270270
$conditions = '';
271271
$attributeField = '';
272272
foreach ($combine->getConditions() as $condition) {
273-
if ($condition->getData('attribute') === \Magento\Catalog\Api\Data\ProductInterface::SKU) {
273+
if ($condition->getData('attribute') === \Magento\Catalog\Api\Data\ProductInterface::SKU
274+
&& $condition->getData('operator') === '()'
275+
) {
274276
$conditions = $condition->getData('value');
275-
$attributeField = $condition->getMappedSqlField();
277+
$attributeField = $this->_connection->quoteIdentifier($condition->getMappedSqlField());
276278
}
277279
}
278280

279281
if (!empty($conditions) && !empty($attributeField)) {
280-
$conditions = explode(',', $conditions);
281-
foreach ($conditions as &$condition) {
282-
$condition = trim($condition);
283-
}
284-
$conditions = implode(', ', $conditions);
282+
$conditions = $this->_connection->quote(
283+
array_map('trim', explode(',', $conditions))
284+
);
285+
$collection->getSelect()->reset(Select::ORDER);
285286
$collection->getSelect()->order(
286-
$this->_connection->quoteInto(
287-
"FIELD(?, ?)",
288-
[
289-
$attributeField,
290-
$conditions
291-
]
287+
$this->_expressionFactory->create(
288+
['expression' => "FIELD($attributeField, $conditions)"]
292289
)
293290
);
294291
}

dev/tests/integration/testsuite/Magento/Rule/Model/Condition/Sql/BuilderTest.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,20 @@ public function testAttachConditionToCollection(): void
6060
'operator' => '==',
6161
'value' => '2017-09-15',
6262
],
63+
'1--3' => [
64+
'type' => ProductCondition::class,
65+
'attribute' => 'sku',
66+
'operator' => '()',
67+
'value' => ' :( , :) ',
68+
]
6369
],
6470
];
6571

6672
$rule->loadPost($ruleConditionArray);
6773
$this->model->attachConditionToCollection($collection, $rule->getConditions());
6874

69-
$whereString = "/\(category_id IN \('3'\).+\(IFNULL\(`e`\.`entity_id`,.+\) = '2017-09-15'\)/";
70-
$this->assertNotFalse(preg_match($whereString, $collection->getSelectSql(true)));
75+
$whereString = "/\(category_id IN \('3'\).+\(IFNULL\(`e`\.`entity_id`,.+\) = '2017-09-15'\)"
76+
. ".+ORDER BY \(FIELD\(`e`.`sku`, ':\(', ':\)'\)\)/";
77+
$this->assertEquals(1, preg_match($whereString, $collection->getSelectSql(true)));
7178
}
7279
}

0 commit comments

Comments
 (0)