Skip to content

Commit d95cea6

Browse files
🔃 [Magento Community Engineering] Community Contributions - 2.4-develop latest changes
Accepted Community Pull Requests: - #25939: [ProductAlert] Cover Helper Data by Unit Test (by @edenduong) - #25928: [Variable] Cover Variable Data Model by Unit Test (by @edenduong) - #25913: [Backend] Covering the Backend Grid Decoding Helper by UnitTest (by @eduard13) - #25822: MFTF: Extract Action Groups to separate files - magento/module-import-export (by @lbajsarowicz) - #25812: MFTF: Extract Action Groups to separate files - magento/module-reports (by @lbajsarowicz) - #25803: MFTF: Extract Action Groups to separate files - magento/module-shipping (by @lbajsarowicz) - #25792: MFTF: Extract Action Groups to separate files - magento/module-variable (by @lbajsarowicz) - #25791: MFTF: Extract Action Groups to separate files - magento/module-widget (by @lbajsarowicz) - #25765: #25739: fixed issue "grunt clean does not clean generated folder" (by @andrewbess) - #25655: Add escaping on meta properties for open graph (by @NathMorgan) Fixed GitHub Issues: - #25739: grunt clean does not clean generated folder (reported by @gwharton) has been fixed in #25765 by @andrewbess in 2.4-develop branch Related commits: 1. b9ef877 - #25654: Magento OpenGraph meta description / title content bleeding (reported by @NathMorgan) has been fixed in #25655 by @NathMorgan in 2.4-develop branch Related commits: 1. cb1b774
2 parents d875854 + db316fd commit d95cea6

21 files changed

+659
-169
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Backend\Test\Unit\Helper;
9+
10+
use Magento\Backend\Helper\Js;
11+
use PHPUnit\Framework\TestCase;
12+
13+
/**
14+
* Class JsTest
15+
*
16+
* Testing decoding serialized grid data
17+
*/
18+
class JsTest extends TestCase
19+
{
20+
/**
21+
* @var Js
22+
*/
23+
private $helper;
24+
25+
/**
26+
* Set Up
27+
*/
28+
protected function setUp()
29+
{
30+
$this->helper = new Js();
31+
}
32+
33+
/**
34+
* Test decoding the serialized input
35+
*
36+
* @dataProvider getEncodedDataProvider
37+
*
38+
* @param string $encoded
39+
* @param array $expected
40+
*/
41+
public function testDecodeGridSerializedInput(string $encoded, array $expected)
42+
{
43+
$this->assertEquals($expected, $this->helper->decodeGridSerializedInput($encoded));
44+
}
45+
46+
/**
47+
* Get serialized grid input
48+
*
49+
* @return array
50+
*/
51+
public function getEncodedDataProvider(): array
52+
{
53+
return [
54+
'Decoding empty serialized string' => [
55+
'',
56+
[]
57+
],
58+
'Decoding a simplified serialized string' => [
59+
'1&2&3&4',
60+
[1, 2, 3, 4]
61+
],
62+
'Decoding encoded serialized string' => [
63+
'2=dGVzdC1zdHJpbmc=',
64+
[
65+
2 => [
66+
'test-string' => ''
67+
]
68+
]
69+
],
70+
'Decoding multiple encoded serialized strings' => [
71+
'2=dGVzdC1zdHJpbmc=&3=bmV3LXN0cmluZw==',
72+
[
73+
2 => [
74+
'test-string' => ''
75+
],
76+
3 => [
77+
'new-string' => ''
78+
]
79+
]
80+
]
81+
];
82+
}
83+
}

app/code/Magento/Catalog/view/frontend/templates/product/view/opengraph/general.phtml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@
99

1010
<meta property="og:type" content="product" />
1111
<meta property="og:title"
12-
content="<?= /* @noEscape */ $block->stripTags($block->getProduct()->getName()) ?>" />
12+
content="<?= $block->escapeHtmlAttr($block->stripTags($block->getProduct()->getName())) ?>" />
1313
<meta property="og:image"
1414
content="<?= $block->escapeUrl($block->getImage($block->getProduct(), 'product_base_image')->getImageUrl()) ?>" />
1515
<meta property="og:description"
16-
content="<?= /* @noEscape */ $block->stripTags($block->getProduct()->getShortDescription()) ?>" />
16+
content="<?= $block->escapeHtmlAttr($block->stripTags($block->getProduct()->getShortDescription())) ?>" />
1717
<meta property="og:url" content="<?= $block->escapeUrl($block->getProduct()->getProductUrl()) ?>" />
18-
<?php if ($priceAmount = $block->getProduct()->getPriceInfo()->getPrice(\Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE)->getAmount()) :?>
18+
<?php if ($priceAmount = $block->getProduct()
19+
->getPriceInfo()
20+
->getPrice(\Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE)
21+
->getAmount()):?>
1922
<meta property="product:price:amount" content="<?= $block->escapeHtmlAttr($priceAmount) ?>"/>
2023
<?= $block->getChildHtml('meta.currency') ?>
2124
<?php endif;?>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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="AdminCheckDataForImportProductActionGroup">
12+
<arguments>
13+
<argument name="behavior" type="string" defaultValue="Add/Update"/>
14+
<argument name="importFile" type="string"/>
15+
</arguments>
16+
<amOnPage url="{{AdminImportIndexPage.url}}" stepKey="goToImportIndexPage"/>
17+
<waitForPageLoad stepKey="adminImportMainSectionLoad"/>
18+
<selectOption selector="{{AdminImportMainSection.entityType}}" userInput="Products" stepKey="selectProductsOption"/>
19+
<waitForElementVisible selector="{{AdminImportMainSection.importBehavior}}" stepKey="waitForImportBehaviorElementVisible"/>
20+
<selectOption selector="{{AdminImportMainSection.importBehavior}}" userInput="{{behavior}}" stepKey="selectImportBehaviorOption"/>
21+
<attachFile selector="{{AdminImportMainSection.selectFileToImport}}" userInput="{{importFile}}" stepKey="attachFileForImport"/>
22+
<click selector="{{AdminImportHeaderSection.checkDataButton}}" stepKey="clickCheckDataButton"/>
23+
<waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappear"/>
24+
</actionGroup>
25+
</actionGroups>

app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminImportProductsActionGroup.xml

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,28 +36,4 @@
3636
<see selector="{{AdminImportValidationMessagesSection.notice}}" userInput="{{importNoticeMessage}}" stepKey="seeNoticeMessage"/>
3737
<see selector="{{AdminImportValidationMessagesSection.messageByType(importMessageType)}}" userInput="{{importMessage}}" stepKey="seeImportMessage"/>
3838
</actionGroup>
39-
40-
<actionGroup name="AdminImportProductsWithCheckValidationResultActionGroup" extends="AdminImportProductsActionGroup">
41-
<arguments>
42-
<argument name="validationNoticeMessage" type="string"/>
43-
<argument name="validationMessage" type="string" defaultValue="File is valid! To start import process press &quot;Import&quot; button"/>
44-
</arguments>
45-
<waitForElementVisible selector="{{AdminImportValidationMessagesSection.notice}}" after="clickCheckDataButton" stepKey="waitForValidationNoticeMessage"/>
46-
<see selector="{{AdminImportValidationMessagesSection.notice}}" userInput="{{validationNoticeMessage}}" after="waitForValidationNoticeMessage" stepKey="seeValidationNoticeMessage"/>
47-
<see selector="{{AdminImportValidationMessagesSection.success}}" userInput="{{validationMessage}}" after="seeValidationNoticeMessage" stepKey="seeValidationMessage"/>
48-
</actionGroup>
49-
<actionGroup name="AdminCheckDataForImportProductActionGroup">
50-
<arguments>
51-
<argument name="behavior" type="string" defaultValue="Add/Update"/>
52-
<argument name="importFile" type="string"/>
53-
</arguments>
54-
<amOnPage url="{{AdminImportIndexPage.url}}" stepKey="goToImportIndexPage"/>
55-
<waitForPageLoad stepKey="adminImportMainSectionLoad"/>
56-
<selectOption selector="{{AdminImportMainSection.entityType}}" userInput="Products" stepKey="selectProductsOption"/>
57-
<waitForElementVisible selector="{{AdminImportMainSection.importBehavior}}" stepKey="waitForImportBehaviorElementVisible"/>
58-
<selectOption selector="{{AdminImportMainSection.importBehavior}}" userInput="{{behavior}}" stepKey="selectImportBehaviorOption"/>
59-
<attachFile selector="{{AdminImportMainSection.selectFileToImport}}" userInput="{{importFile}}" stepKey="attachFileForImport"/>
60-
<click selector="{{AdminImportHeaderSection.checkDataButton}}" stepKey="clickCheckDataButton"/>
61-
<waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappear"/>
62-
</actionGroup>
6339
</actionGroups>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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="AdminImportProductsWithCheckValidationResultActionGroup" extends="AdminImportProductsActionGroup">
12+
<arguments>
13+
<argument name="validationNoticeMessage" type="string"/>
14+
<argument name="validationMessage" type="string" defaultValue="File is valid! To start import process press &quot;Import&quot; button"/>
15+
</arguments>
16+
<waitForElementVisible selector="{{AdminImportValidationMessagesSection.notice}}" after="clickCheckDataButton" stepKey="waitForValidationNoticeMessage"/>
17+
<see selector="{{AdminImportValidationMessagesSection.notice}}" userInput="{{validationNoticeMessage}}" after="waitForValidationNoticeMessage" stepKey="seeValidationNoticeMessage"/>
18+
<see selector="{{AdminImportValidationMessagesSection.success}}" userInput="{{validationMessage}}" after="seeValidationNoticeMessage" stepKey="seeValidationMessage"/>
19+
</actionGroup>
20+
</actionGroups>
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\ProductAlert\Test\Unit\Helper;
9+
10+
use PHPUnit\Framework\TestCase;
11+
use Magento\ProductAlert\Helper\Data as HelperData;
12+
use Magento\Framework\App\Helper\Context;
13+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
14+
use Magento\Framework\UrlInterface;
15+
use Magento\Framework\Url\EncoderInterface;
16+
use Magento\Catalog\Model\Product;
17+
use Magento\Framework\App\Config\ScopeConfigInterface;
18+
use Magento\ProductAlert\Model\Observer;
19+
use Magento\Store\Model\ScopeInterface;
20+
use Magento\Framework\View\LayoutInterface;
21+
use Magento\ProductAlert\Block\Email\Price;
22+
use Magento\Framework\Exception\LocalizedException;
23+
24+
class DataTest extends TestCase
25+
{
26+
/**
27+
* @var HelperData
28+
*/
29+
private $helper;
30+
31+
/**
32+
* @var ObjectManagerHelper
33+
*/
34+
private $objectManagerHelper;
35+
36+
/**
37+
* @var Context|\PHPUnit_Framework_MockObject_MockObject
38+
*/
39+
private $contextMock;
40+
41+
/**
42+
* @var UrlInterface|\PHPUnit_Framework_MockObject_MockObject
43+
*/
44+
private $urlBuilderMock;
45+
46+
/**
47+
* @var EncoderInterface|\PHPUnit_Framework_MockObject_MockObject
48+
*/
49+
private $encoderMock;
50+
51+
/**
52+
* @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject
53+
*/
54+
private $scopeConfigMock;
55+
56+
/**
57+
* @var LayoutInterface|\PHPUnit_Framework_MockObject_MockObject
58+
*/
59+
private $layoutMock;
60+
61+
/**
62+
* Setup environment for testing
63+
*/
64+
protected function setUp()
65+
{
66+
$this->contextMock = $this->createMock(Context::class);
67+
$this->urlBuilderMock = $this->createMock(UrlInterface::class);
68+
$this->encoderMock = $this->createMock(EncoderInterface::class);
69+
$this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class);
70+
$this->layoutMock = $this->createMock(LayoutInterface::class);
71+
$this->contextMock->expects($this->once())->method('getUrlBuilder')->willReturn($this->urlBuilderMock);
72+
$this->contextMock->expects($this->once())->method('getUrlEncoder')->willReturn($this->encoderMock);
73+
$this->contextMock->expects($this->once())->method('getScopeConfig')->willReturn($this->scopeConfigMock);
74+
75+
$this->objectManagerHelper = new ObjectManagerHelper($this);
76+
77+
$productMock = $this->createMock(Product::class);
78+
$productMock->expects($this->any())->method('getId')->willReturn(1);
79+
80+
$this->helper = $this->objectManagerHelper->getObject(
81+
HelperData::class,
82+
[
83+
'context' => $this->contextMock,
84+
'layout' => $this->layoutMock
85+
]
86+
);
87+
$this->helper->setProduct($productMock);
88+
}
89+
90+
/**
91+
* Test getSaveUrl() function
92+
*/
93+
public function testGetSaveUrl()
94+
{
95+
$currentUrl = 'http://www.example.com/';
96+
$type = 'stock';
97+
$uenc = strtr(base64_encode($currentUrl), '+/=', '-_,');
98+
$expected = 'http://www.example.com/roductalert/add/stock/product_id/1/uenc/' . $uenc;
99+
100+
$this->urlBuilderMock->expects($this->any())->method('getCurrentUrl')->willReturn($currentUrl);
101+
$this->encoderMock->expects($this->any())->method('encode')
102+
->with($currentUrl)
103+
->willReturn($uenc);
104+
$this->urlBuilderMock->expects($this->any())->method('getUrl')
105+
->with(
106+
'productalert/add/' . $type,
107+
[
108+
'product_id' => 1,
109+
'uenc' => $uenc
110+
]
111+
)
112+
->willReturn($expected);
113+
114+
$this->assertEquals($expected, $this->helper->getSaveUrl($type));
115+
}
116+
117+
/**
118+
* Test createBlock() with no exception
119+
*/
120+
public function testCreateBlockWithNoException()
121+
{
122+
$priceBlockMock = $this->createMock(Price::class);
123+
$this->layoutMock->expects($this->once())->method('createBlock')->willReturn($priceBlockMock);
124+
125+
$this->assertEquals($priceBlockMock, $this->helper->createBlock(Price::class));
126+
}
127+
128+
/**
129+
* Test createBlock() with exception
130+
*/
131+
public function testCreateBlockWithException()
132+
{
133+
$invalidBlock = $this->createMock(Product::class);
134+
$this->expectException(LocalizedException::class);
135+
136+
$this->helper->createBlock($invalidBlock);
137+
}
138+
139+
/**
140+
* Test isStockAlertAllowed() function with Yes settings
141+
*/
142+
public function testIsStockAlertAllowedWithYesSettings()
143+
{
144+
$this->scopeConfigMock->expects($this->any())->method('isSetFlag')
145+
->with(Observer::XML_PATH_STOCK_ALLOW, ScopeInterface::SCOPE_STORE)
146+
->willReturn('1');
147+
148+
$this->assertEquals('1', $this->helper->isStockAlertAllowed());
149+
}
150+
151+
/**
152+
* Test isPriceAlertAllowed() function with Yes settings
153+
*/
154+
public function testIsPriceAlertAllowedWithYesSetting()
155+
{
156+
$this->scopeConfigMock->expects($this->any())->method('isSetFlag')
157+
->with(Observer::XML_PATH_PRICE_ALLOW, ScopeInterface::SCOPE_STORE)
158+
->willReturn('1');
159+
160+
$this->assertEquals('1', $this->helper->isPriceAlertAllowed());
161+
}
162+
}

app/code/Magento/Reports/Test/Mftf/ActionGroup/GenerateOrderReportActionGroup.xml

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,11 @@
1616
<argument name="orderFromDate" type="string"/>
1717
<argument name="orderToDate" type="string"/>
1818
</arguments>
19-
19+
2020
<click selector="{{OrderReportMainSection.here}}" stepKey="clickOnHere"/>
2121
<fillField selector="{{OrderReportFilterSection.dateFrom}}" userInput="{{orderFromDate}}" stepKey="fillFromDate"/>
2222
<fillField selector="{{OrderReportFilterSection.dateTo}}" userInput="{{orderToDate}}" stepKey="fillToDate"/>
2323
<selectOption selector="{{OrderReportFilterSection.orderStatus}}" userInput="Any" stepKey="selectAnyOption"/>
2424
<click selector="{{OrderReportMainSection.showReport}}" stepKey="showReport"/>
2525
</actionGroup>
26-
27-
<actionGroup name="GenerateOrderReportForNotCancelActionGroup">
28-
<annotations>
29-
<description>Clicks on 'here' to refresh the grid data. Enters the provided Order From/To Dates and provided Order Status. Clicks on 'Show Report'.</description>
30-
</annotations>
31-
<arguments>
32-
<argument name="orderFromDate" type="string"/>
33-
<argument name="orderToDate" type="string"/>
34-
<argument name="statuses" type="string"/>
35-
</arguments>
36-
37-
<click selector="{{OrderReportMainSection.here}}" stepKey="clickOnHere"/>
38-
<fillField selector="{{OrderReportFilterSection.dateFrom}}" userInput="{{orderFromDate}}" stepKey="fillFromDate"/>
39-
<fillField selector="{{OrderReportFilterSection.dateTo}}" userInput="{{orderToDate}}" stepKey="fillToDate"/>
40-
<selectOption selector="{{OrderReportFilterSection.orderStatus}}" userInput="Specified" stepKey="selectSpecifiedOption"/>
41-
<selectOption selector="{{OrderReportFilterSection.orderStatusSpecified}}" parameterArray="{{statuses}}" stepKey="selectSpecifiedOptionStatus"/>
42-
<click selector="{{OrderReportMainSection.showReport}}" stepKey="showReport"/>
43-
</actionGroup>
4426
</actionGroups>

0 commit comments

Comments
 (0)