Skip to content

Commit fa25a53

Browse files
authored
Merge branch '2.4-develop' into issue-24635
2 parents 8317e93 + 4898eb4 commit fa25a53

File tree

11 files changed

+254
-192
lines changed

11 files changed

+254
-192
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd">
10+
<entity name="SystemUploadConfigurationMaxWidth">
11+
<data key="path">system/upload_configuration/max_width</data>
12+
<data key="value">1920</data>
13+
</entity>
14+
<entity name="SystemUploadConfigurationMaxHeight">
15+
<data key="path">system/upload_configuration/max_height</data>
16+
<data key="value">1200</data>
17+
</entity>
18+
</entities>

app/code/Magento/CatalogInventory/Model/Indexer/Stock/CacheCleaner.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
namespace Magento\CatalogInventory\Model\Indexer\Stock;
88

9+
use Magento\Catalog\Model\Category;
910
use Magento\CatalogInventory\Api\StockConfigurationInterface;
1011
use Magento\Framework\App\ResourceConnection;
1112
use Magento\Framework\App\ObjectManager;
@@ -88,6 +89,11 @@ public function clean(array $productIds, callable $reindex)
8889
if ($productIds) {
8990
$this->cacheContext->registerEntities(Product::CACHE_TAG, array_unique($productIds));
9091
$this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->cacheContext]);
92+
$categoryIds = $this->getCategoryIdsByProductIds($productIds);
93+
if ($categoryIds){
94+
$this->cacheContext->registerEntities(Category::CACHE_TAG, array_unique($categoryIds));
95+
$this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->cacheContext]);
96+
}
9197
}
9298
}
9399

@@ -159,6 +165,22 @@ private function getProductIdsForCacheClean(array $productStatusesBefore, array
159165
return $productIds;
160166
}
161167

168+
/**
169+
* Get category ids for products
170+
*
171+
* @param array $productIds
172+
* @return array
173+
*/
174+
private function getCategoryIdsByProductIds(array $productIds): array
175+
{
176+
$categoryProductTable = $this->getConnection()->getTableName('catalog_category_product');
177+
$select = $this->getConnection()->select()
178+
->from(['catalog_category_product' => $categoryProductTable], ['category_id'])
179+
->where('product_id IN (?)', $productIds);
180+
181+
return $this->getConnection()->fetchCol($select);
182+
}
183+
162184
/**
163185
* Get database connection.
164186
*

app/code/Magento/CatalogInventory/Test/Unit/Model/Indexer/Stock/CacheCleanerTest.php

Lines changed: 86 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace Magento\CatalogInventory\Test\Unit\Model\Indexer\Stock;
99

10+
use Magento\Catalog\Model\Category;
1011
use Magento\Catalog\Model\Product;
1112
use Magento\CatalogInventory\Api\StockConfigurationInterface;
1213
use Magento\CatalogInventory\Model\Indexer\Stock\CacheCleaner;
@@ -20,6 +21,9 @@
2021
use PHPUnit\Framework\MockObject\MockObject;
2122
use PHPUnit\Framework\TestCase;
2223

24+
/**
25+
* Test for CacheCleaner
26+
*/
2327
class CacheCleanerTest extends TestCase
2428
{
2529
/**
@@ -70,14 +74,16 @@ protected function setUp(): void
7074
$this->connectionMock = $this->getMockBuilder(AdapterInterface::class)
7175
->getMock();
7276
$this->stockConfigurationMock = $this->getMockBuilder(StockConfigurationInterface::class)
73-
->setMethods(['getStockThresholdQty'])->getMockForAbstractClass();
77+
->setMethods(['getStockThresholdQty'])
78+
->getMockForAbstractClass();
7479
$this->cacheContextMock = $this->getMockBuilder(CacheContext::class)
7580
->disableOriginalConstructor()
7681
->getMock();
7782
$this->eventManagerMock = $this->getMockBuilder(ManagerInterface::class)
7883
->getMock();
7984
$this->metadataPoolMock = $this->getMockBuilder(MetadataPool::class)
80-
->setMethods(['getMetadata', 'getLinkField'])->disableOriginalConstructor()
85+
->setMethods(['getMetadata', 'getLinkField'])
86+
->disableOriginalConstructor()
8187
->getMock();
8288
$this->selectMock = $this->getMockBuilder(Select::class)
8389
->disableOriginalConstructor()
@@ -100,37 +106,63 @@ protected function setUp(): void
100106
}
101107

102108
/**
109+
* Test clean cache by product ids and category ids
110+
*
103111
* @param bool $stockStatusBefore
104112
* @param bool $stockStatusAfter
105113
* @param int $qtyAfter
106114
* @param bool|int $stockThresholdQty
107115
* @dataProvider cleanDataProvider
116+
* @return void
108117
*/
109-
public function testClean($stockStatusBefore, $stockStatusAfter, $qtyAfter, $stockThresholdQty)
118+
public function testClean($stockStatusBefore, $stockStatusAfter, $qtyAfter, $stockThresholdQty): void
110119
{
111120
$productId = 123;
112-
$this->selectMock->expects($this->any())->method('from')->willReturnSelf();
113-
$this->selectMock->expects($this->any())->method('where')->willReturnSelf();
114-
$this->selectMock->expects($this->any())->method('joinLeft')->willReturnSelf();
115-
$this->connectionMock->expects($this->exactly(2))->method('select')->willReturn($this->selectMock);
116-
$this->connectionMock->expects($this->exactly(2))->method('fetchAll')->willReturnOnConsecutiveCalls(
117-
[
118-
['product_id' => $productId, 'stock_status' => $stockStatusBefore],
119-
],
120-
[
121-
['product_id' => $productId, 'stock_status' => $stockStatusAfter, 'qty' => $qtyAfter],
122-
]
123-
);
124-
$this->stockConfigurationMock->expects($this->once())->method('getStockThresholdQty')
121+
$categoryId = 3;
122+
$this->selectMock->expects($this->any())
123+
->method('from')
124+
->willReturnSelf();
125+
$this->selectMock->expects($this->any())
126+
->method('where')
127+
->willReturnSelf();
128+
$this->selectMock->expects($this->any())
129+
->method('joinLeft')
130+
->willReturnSelf();
131+
$this->connectionMock->expects($this->exactly(3))
132+
->method('select')
133+
->willReturn($this->selectMock);
134+
$this->connectionMock->expects($this->exactly(2))
135+
->method('fetchAll')
136+
->willReturnOnConsecutiveCalls(
137+
[
138+
['product_id' => $productId, 'stock_status' => $stockStatusBefore],
139+
],
140+
[
141+
['product_id' => $productId, 'stock_status' => $stockStatusAfter, 'qty' => $qtyAfter],
142+
]
143+
);
144+
$this->connectionMock->expects($this->exactly(1))
145+
->method('fetchCol')
146+
->willReturn([$categoryId]);
147+
$this->stockConfigurationMock->expects($this->once())
148+
->method('getStockThresholdQty')
125149
->willReturn($stockThresholdQty);
126-
$this->cacheContextMock->expects($this->once())->method('registerEntities')
127-
->with(Product::CACHE_TAG, [$productId]);
128-
$this->eventManagerMock->expects($this->once())->method('dispatch')
150+
$this->cacheContextMock->expects($this->exactly(2))
151+
->method('registerEntities')
152+
->withConsecutive(
153+
[Product::CACHE_TAG, [$productId]],
154+
[Category::CACHE_TAG, [$categoryId]],
155+
);
156+
$this->eventManagerMock->expects($this->exactly(2))
157+
->method('dispatch')
129158
->with('clean_cache_by_tags', ['object' => $this->cacheContextMock]);
130-
$this->metadataPoolMock->expects($this->exactly(2))->method('getMetadata')
159+
$this->metadataPoolMock->expects($this->exactly(2))
160+
->method('getMetadata')
131161
->willReturnSelf();
132-
$this->metadataPoolMock->expects($this->exactly(2))->method('getLinkField')
162+
$this->metadataPoolMock->expects($this->exactly(2))
163+
->method('getLinkField')
133164
->willReturn('row_id');
165+
134166
$callback = function () {
135167
};
136168
$this->unit->clean([], $callback);
@@ -139,7 +171,7 @@ public function testClean($stockStatusBefore, $stockStatusAfter, $qtyAfter, $sto
139171
/**
140172
* @return array
141173
*/
142-
public function cleanDataProvider()
174+
public function cleanDataProvider(): array
143175
{
144176
return [
145177
[true, false, 1, false],
@@ -155,29 +187,42 @@ public function cleanDataProvider()
155187
* @param int $qtyAfter
156188
* @param bool|int $stockThresholdQty
157189
* @dataProvider notCleanCacheDataProvider
190+
* @return void
158191
*/
159-
public function testNotCleanCache($stockStatusBefore, $stockStatusAfter, $qtyAfter, $stockThresholdQty)
192+
public function testNotCleanCache($stockStatusBefore, $stockStatusAfter, $qtyAfter, $stockThresholdQty): void
160193
{
161194
$productId = 123;
162-
$this->selectMock->expects($this->any())->method('from')->willReturnSelf();
163-
$this->selectMock->expects($this->any())->method('where')->willReturnSelf();
164-
$this->selectMock->expects($this->any())->method('joinLeft')->willReturnSelf();
165-
$this->connectionMock->expects($this->exactly(2))->method('select')->willReturn($this->selectMock);
166-
$this->connectionMock->expects($this->exactly(2))->method('fetchAll')->willReturnOnConsecutiveCalls(
167-
[
168-
['product_id' => $productId, 'stock_status' => $stockStatusBefore],
169-
],
170-
[
171-
['product_id' => $productId, 'stock_status' => $stockStatusAfter, 'qty' => $qtyAfter],
172-
]
173-
);
174-
$this->stockConfigurationMock->expects($this->once())->method('getStockThresholdQty')
195+
$this->selectMock->expects($this->any())->method('from')
196+
->willReturnSelf();
197+
$this->selectMock->expects($this->any())->method('where')
198+
->willReturnSelf();
199+
$this->selectMock->expects($this->any())->method('joinLeft')
200+
->willReturnSelf();
201+
$this->connectionMock->expects($this->exactly(2))
202+
->method('select')
203+
->willReturn($this->selectMock);
204+
$this->connectionMock->expects($this->exactly(2))
205+
->method('fetchAll')
206+
->willReturnOnConsecutiveCalls(
207+
[
208+
['product_id' => $productId, 'stock_status' => $stockStatusBefore],
209+
],
210+
[
211+
['product_id' => $productId, 'stock_status' => $stockStatusAfter, 'qty' => $qtyAfter],
212+
]
213+
);
214+
$this->stockConfigurationMock->expects($this->once())
215+
->method('getStockThresholdQty')
175216
->willReturn($stockThresholdQty);
176-
$this->cacheContextMock->expects($this->never())->method('registerEntities');
177-
$this->eventManagerMock->expects($this->never())->method('dispatch');
178-
$this->metadataPoolMock->expects($this->exactly(2))->method('getMetadata')
217+
$this->cacheContextMock->expects($this->never())
218+
->method('registerEntities');
219+
$this->eventManagerMock->expects($this->never())
220+
->method('dispatch');
221+
$this->metadataPoolMock->expects($this->exactly(2))
222+
->method('getMetadata')
179223
->willReturnSelf();
180-
$this->metadataPoolMock->expects($this->exactly(2))->method('getLinkField')
224+
$this->metadataPoolMock->expects($this->exactly(2))
225+
->method('getLinkField')
181226
->willReturn('row_id');
182227

183228
$callback = function () {
@@ -188,7 +233,7 @@ public function testNotCleanCache($stockStatusBefore, $stockStatusAfter, $qtyAft
188233
/**
189234
* @return array
190235
*/
191-
public function notCleanCacheDataProvider()
236+
public function notCleanCacheDataProvider(): array
192237
{
193238
return [
194239
[true, true, 1, false],

app/code/Magento/Cms/Test/Mftf/Data/CmsPageData.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,19 @@
8888
<data key="height">1000</data>
8989
<data key="path">wysiwyg</data>
9090
</entity>
91+
<entity name="ImageUploadMedium" type="uploadImage">
92+
<data key="title" unique="suffix">Medium Image</data>
93+
<data key="price">1.00</data>
94+
<data key="file_type">Upload File</data>
95+
<data key="shareable">Yes</data>
96+
<data key="value">medium.jpg</data>
97+
<data key="file">medium.jpg</data>
98+
<data key="fileName">medium</data>
99+
<data key="extension">jpg</data>
100+
<data key="content">Image content. Yeah.</data>
101+
<data key="height">508</data>
102+
<data key="path">wysiwyg</data>
103+
</entity>
91104
<entity name="ImageFolder" type="uploadImage">
92105
<data key="name" unique="suffix">Test</data>
93106
</entity>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<section name="StorefrontCMSPageSection">
1212
<element name="mediaDescription" type="text" selector=".column.main>p>img"/>
1313
<element name="imageSource" type="text" selector="//img[contains(@src,'{{imageName}}')]" parameterized="true"/>
14+
<element name="imageBySource" type="text" selector="img[src*='{{imageName}}']" parameterized="true"/>
1415
<element name="mainTitle" type="text" selector="#maincontent .page-title"/>
1516
<element name="mainContent" type="text" selector="#maincontent"/>
1617
<element name="footerTop" type="text" selector="footer.page-footer"/>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
10+
<test name="AdminAddLargeImageToWYSIWYGCMSTest">
11+
<annotations>
12+
<features value="Cms"/>
13+
<stories value="Default WYSIWYG toolbar configuration with Magento Media Gallery"/>
14+
<group value="Cms"/>
15+
<title value="Resize image for CMS according to Upload Configuration"/>
16+
<description value="The large image should be resized according to Upload Configuration"/>
17+
<severity value="BLOCKER"/>
18+
<testCaseId value="MC-41826"/>
19+
</annotations>
20+
<before>
21+
<createData entity="_defaultCmsPage" stepKey="createCMSPage" />
22+
<actionGroup ref="AdminLoginActionGroup" stepKey="login"/>
23+
<actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/>
24+
<actionGroup ref="CliEnableTinyMCE4ActionGroup" stepKey="switchToTinyMCE4" />
25+
</before>
26+
<after>
27+
<deleteData createDataKey="createCMSPage" stepKey="deleteCMSPage" />
28+
<actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/>
29+
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>
30+
</after>
31+
32+
<actionGroup ref="NavigateToCreatedCMSPageActionGroup" stepKey="navigateToCreatedCMSPage">
33+
<argument name="CMSPage" value="$$createCMSPage$$"/>
34+
</actionGroup>
35+
<waitForElementVisible selector="{{TinyMCESection.TinyMCE4}}" stepKey="waitForTinyMCE4" />
36+
<click selector="{{TinyMCESection.InsertImageIcon}}" stepKey="clickInsertImageIcon" />
37+
<waitForPageLoad stepKey="waitForPageLoad" />
38+
<actionGroup ref="ClickBrowseBtnOnUploadPopupActionGroup" stepKey="clickBrowserBtn"/>
39+
<actionGroup ref="AttachImageActionGroup" stepKey="attachImage">
40+
<argument name="Image" value="ImageUploadMedium"/>
41+
</actionGroup>
42+
<actionGroup ref="SaveImageActionGroup" stepKey="insertImage"/>
43+
<actionGroup ref="FillOutUploadImagePopupActionGroup" stepKey="fillOutUploadImagePopup" />
44+
<click selector="{{CmsNewPagePageSeoSection.header}}" stepKey="clickExpandSearchEngineOptimisation"/>
45+
<fillField selector="{{CmsNewPagePageSeoSection.urlKey}}" userInput="$$createCMSPage.identifier$$" stepKey="fillFieldUrlKey"/>
46+
<actionGroup ref="SaveCmsPageActionGroup" stepKey="clickSavePage"/>
47+
<amOnPage url="$$createCMSPage.identifier$$" stepKey="amOnPageTestPage"/>
48+
<waitForPageLoad stepKey="waitPageLoadOnFrontend"/>
49+
<seeElementInDOM selector="{{StorefrontCMSPageSection.imageSource(ImageUploadMedium.fileName)}}" stepKey="assertMediaSource"/>
50+
<executeJS function='return document.querySelector("{{StorefrontCMSPageSection.imageBySource(ImageUploadMedium.fileName)}}").naturalWidth;' stepKey="imageNaturalWith"/>
51+
<assertLessThanOrEqual stepKey="assertMaxImageWith">
52+
<expectedResult type="int">{{SystemUploadConfigurationMaxWidth.value}}</expectedResult>
53+
<actualResult type="variable">imageNaturalWith</actualResult>
54+
</assertLessThanOrEqual>
55+
<executeJS function='return document.querySelector("{{StorefrontCMSPageSection.imageBySource(ImageUploadMedium.fileName)}}").naturalHeight;' stepKey="imageNaturalHeight"/>
56+
<assertLessThanOrEqual stepKey="assertMaxImageHeight">
57+
<expectedResult type="int">{{SystemUploadConfigurationMaxHeight.value}}</expectedResult>
58+
<actualResult type="variable">imageNaturalHeight</actualResult>
59+
</assertLessThanOrEqual>
60+
</test>
61+
</tests>

0 commit comments

Comments
 (0)