Skip to content

Commit 654d288

Browse files
authored
Merge branch '2.4-develop' into issues/35808
2 parents 95e63e5 + 5a2037c commit 654d288

File tree

79 files changed

+1648
-1089
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+1648
-1089
lines changed

app/code/Magento/ApplicationPerformanceMonitor/README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
**ApplicationPerformanceMonitor**
1+
# ApplicationPerformanceMonitor
22

33
Monitors the Performance of the Application
44

55
To configure, edit app/etc/env.php
66
Add these lines.
77

8-
```
8+
```php
99
'application' => [
1010
'performance_monitor' => [
1111
'logger_output_enable' => 1,
@@ -21,7 +21,8 @@ The option `logger_output_enable` enables outputting performance metrics to the
2121
The option `logger_output_verbose` adds additional metrics.
2222

2323
Example output in log file without verbose:
24-
```
24+
25+
```log
2526
[2023-10-04T20:48:23.727037+00:00] report.ERROR: "Profile information": {
2627
"applicationClass": "Magento\ApplicationServer\App\Application\Interceptor",
2728
"applicationServer": "1",
@@ -36,7 +37,8 @@ Example output in log file without verbose:
3637
```
3738

3839
Example output in log file with verbose:
39-
```
40+
41+
```log
4042
[2023-10-04T20:55:31.174304+00:00] report.ERROR: "Profile information": {
4143
"applicationClass": "Magento\ApplicationServer\App\Application\Interceptor",
4244
"applicationServer": "1",

app/code/Magento/ApplicationPerformanceMonitorNewRelic/README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1-
**ApplicationPerformanceMonitorNewRelic**
1+
# ApplicationPerformanceMonitorNewRelic
22

33
Monitors the Performance of the Application in New Relic
44

55
To use this module, it requires a New Relic account and the environment already by configured to use that account.
6-
For general New Relic PHP configuration information, see https://docs.newrelic.com/docs/apm/agents/php-agent/configuration/php-agent-configuration/ .
6+
For general New Relic PHP configuration information, see <https://docs.newrelic.com/docs/apm/agents/php-agent/configuration/php-agent-configuration/>.
77

8-
To configure this module, edit app/etc/env.php
8+
To configure this module, edit `app/etc/env.php`.
99
Add these lines.
1010

11-
```
11+
```php
1212
'application' => [
1313
'performance_monitor' => [
1414
'newrelic_output_enable' => 1,
1515
'newrelic_output_verbose' => 0,
1616
]
1717
]
1818
```
19+
1920
Use 0 or 1 as the value to enable or disable.
2021
`newrelic_output_enable` defaults to 1, and `newrelic_output_verbose` defaults to 0.
2122

app/code/Magento/Backend/view/adminhtml/templates/dashboard/totalbar/refreshstatistics.phtml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,31 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
7+
/** @var \Magento\Backend\Block\Template $block */
8+
/** @var \Magento\Framework\Escaper $escaper */
69
?>
710
<div class="page-actions">
811
<div class="page-actions-inner">
912
<div class="page-actions-buttons">
1013
<?= $block->getChildHtml() ?>
1114

15+
<?php if ($block->getAuthorization()->isAllowed('Magento_Reports::statistics')): ?>
1216
<form class="action-element"
13-
action="<?= $block->escapeUrl($block->getUrl('*/*/refreshStatistics')) ?>"
17+
action="<?= $escaper->escapeUrl($block->getUrl('*/*/refreshStatistics')) ?>"
1418
method="post">
1519
<input
1620
name="form_key"
1721
type="hidden"
18-
value="<?= $block->escapeHtmlAttr($block->getFormKey()) ?>"/>
22+
value="<?= $escaper->escapeHtmlAttr($block->getFormKey()) ?>"/>
1923
<button
2024
class="action-primary"
2125
type="submit"
22-
title="<?= $block->escapeHtmlAttr(__('Reload Data')) ?>">
23-
<?= $block->escapeHtml(__('Reload Data')) ?>
26+
title="<?= $escaper->escapeHtmlAttr(__('Reload Data')) ?>">
27+
<?= $escaper->escapeHtml(__('Reload Data')) ?>
2428
</button>
2529
</form>
30+
<?php endif; ?>
2631
</div>
2732
</div>
2833
</div>
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
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="StorefrontApplyTierPriceForBundleDynamicProductTest">
12+
<annotations>
13+
<features value="Bundle Product"/>
14+
<stories value="Dynamic Bundle Product with Tier Price"/>
15+
<title value="Apply Tier price for Bundle Dynamic Product"/>
16+
<description value="Create bundled product with tier price and verify price and tier price % in customization frame in storefront."/>
17+
<severity value="MAJOR"/>
18+
<testCaseId value="AC-4051"/>
19+
</annotations>
20+
<before>
21+
<!--Create a category-->
22+
<createData entity="SimpleSubCategory" stepKey="createCategory"/>
23+
<!-- simple product1-->
24+
<createData entity="SimpleProduct" stepKey="SimpleProduct1">
25+
<field key="price">110.00</field>
26+
<requiredEntity createDataKey="createCategory"/>
27+
</createData>
28+
<!-- simple product2 -->
29+
<createData entity="SimpleProduct" stepKey="SimpleProduct2">
30+
<field key="price">40.00</field>
31+
<requiredEntity createDataKey="createCategory"/>
32+
</createData>
33+
<createData entity="ApiBundleProduct" stepKey="createBundleProduct">
34+
<requiredEntity createDataKey="createCategory"/>
35+
</createData>
36+
<createData entity="DropDownBundleOption" stepKey="dropDownBundleOption1">
37+
<requiredEntity createDataKey="createBundleProduct"/>
38+
</createData>
39+
<createData entity="ApiBundleLink" stepKey="LinkOptionToFirstProduct1">
40+
<requiredEntity createDataKey="createBundleProduct"/>
41+
<requiredEntity createDataKey="dropDownBundleOption1"/>
42+
<requiredEntity createDataKey="SimpleProduct1"/>
43+
</createData>
44+
<createData entity="ApiBundleLink" stepKey="LinkOptionToSecondProduct12">
45+
<requiredEntity createDataKey="createBundleProduct"/>
46+
<requiredEntity createDataKey="dropDownBundleOption1"/>
47+
<requiredEntity createDataKey="SimpleProduct2"/>
48+
</createData>
49+
<!-- Login as admin -->
50+
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
51+
<actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="openGridForBundleProduct1"/>
52+
<actionGroup ref="FilterProductGridBySkuActionGroup" stepKey="filterBundleProduct1">
53+
<argument name="product" value="$$createBundleProduct$$"/>
54+
</actionGroup>
55+
<actionGroup ref="OpenProductForEditByClickingRowXColumnYInProductGridActionGroup" stepKey="openFirstProductForEdit"/>
56+
<actionGroup ref="AdminBundleProductSetAdvancedPricingActionGroup" stepKey="addProductTierPrice">
57+
<argument name="quantity" value="2"/>
58+
<argument name="price" value="Discount"/>
59+
<argument name="amount" value="20"/>
60+
<argument name="priceView" value="Price Range"/>
61+
</actionGroup>
62+
<actionGroup ref="SetCategoryByNameActionGroup" stepKey="addCategoryToBundledProduct">
63+
<argument name="categoryName" value="$$createCategory.name$$"/>
64+
</actionGroup>
65+
<actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/>
66+
<actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex">
67+
<argument name="indices" value=""/>
68+
</actionGroup>
69+
<actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanCache">
70+
<argument name="tags" value="config full_page"/>
71+
</actionGroup>
72+
</before>
73+
<after>
74+
<!-- Delete the simple product -->
75+
<deleteData createDataKey="SimpleProduct1" stepKey="deleteSimpleProduct1"/>
76+
<!-- Delete the simple product -->
77+
<deleteData createDataKey="SimpleProduct2" stepKey="deleteSimpleProduct2"/>
78+
<!--Delete category-->
79+
<deleteData createDataKey="createCategory" stepKey="deleteCategory"/>
80+
<!--Delete Bundle Product-->
81+
<deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/>
82+
<!-- Log out -->
83+
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>
84+
</after>
85+
<!--Open created category in storefront and assert the price-->
86+
<actionGroup ref="StorefrontGoToCategoryPageActionGroup" stepKey="againOpenEnabledCategory">
87+
<argument name="categoryName" value="$$createCategory.name$$"/>
88+
</actionGroup>
89+
<waitForText userInput="From $40.00" selector="{{StorefrontCategoryProductSection.priceFromByProductId($$createBundleProduct.id$$)}}" stepKey="seeFromPriceFromInCategoryBundle"/>
90+
<waitForText userInput="To $110.00" selector="{{StorefrontCategoryProductSection.priceToByProductId($$createBundleProduct.id$$)}}" stepKey="seeToPriceFromInCategoryBundle"/>
91+
<!--Open Bundled product-->
92+
<actionGroup ref="StorefrontOpenProductEntityPageActionGroup" stepKey="navigateToProduct2ProductDetailsPage">
93+
<argument name="product" value="$createBundleProduct$"/>
94+
</actionGroup>
95+
<!--Click on Customize and Add to cart-->
96+
<actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickButtonToCustomize"/>
97+
<actionGroup ref="StorefrontSelectBundleProductDropDownOptionActionGroup" stepKey="addSimpleProduct1">
98+
<argument name="productName" value="$SimpleProduct1.name$"/>
99+
</actionGroup>
100+
<!-- Assert price and tier price %-->
101+
<waitForText userInput="$110.00" selector="{{StorefrontBundledSection.bundleProductsPrice}}" stepKey="seeCustomizationPrice"/>
102+
<waitForText userInput="Buy 2 with 20% discount each" selector="{{StorefrontProductInfoMainSection.tierPriceWithIndex('1')}}" stepKey="tierPriceText"/>
103+
<!-- Change qty in customization frame nd add it to cart-->
104+
<actionGroup ref="StorefrontEnterProductQuantityAndAddToTheCartActionGroup" stepKey="enterProductQuantityAndAddToTheCart">
105+
<argument name="quantity" value="2"/>
106+
</actionGroup>
107+
<!--Select 2nd product in from the bundled product and add qty 2 to cart-->
108+
<actionGroup ref="StorefrontSelectBundleProductDropDownOptionActionGroup" stepKey="addSimpleProduct2">
109+
<argument name="productName" value="$SimpleProduct2.name$"/>
110+
</actionGroup>
111+
<actionGroup ref="StorefrontEnterProductQuantityAndAddToTheCartActionGroup" stepKey="enterProductQuantityForProduct2AndAddToTheCart">
112+
<argument name="quantity" value="2"/>
113+
</actionGroup>
114+
<!--Go to cart page and assert the discounted price-->
115+
<actionGroup ref="StorefrontCartPageOpenActionGroup" stepKey="goToCartPage" />
116+
<see stepKey="seeNewPriceInCart" selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$240.00"/>
117+
</test>
118+
</tests>

app/code/Magento/Bundle/view/frontend/requirejs-config.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,12 @@ var config = {
1111
slide: 'Magento_Bundle/js/slide',
1212
productSummary: 'Magento_Bundle/js/product-summary'
1313
}
14+
},
15+
config: {
16+
mixins: {
17+
'mage/validation': {
18+
'Magento_Bundle/js/validation': true
19+
}
20+
}
1421
}
1522
};

app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/checkbox.phtml

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,59 +5,65 @@
55
*/
66
?>
77

8-
<?php /* @var $block \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle\Option\Checkbox */ ?>
8+
<?php
9+
/**
10+
* @var $block \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle\Option\Checkbox
11+
* @var \Magento\Framework\Escaper $escaper
12+
*/
13+
?>
914
<?php $_option = $block->getOption() ?>
1015
<?php $_selections = $_option->getSelections() ?>
11-
<?php $inputClass = 'checkbox product bundle option bundle-option-' . $block->escapeHtmlAttr($_option->getId()) ?>
12-
<?php $inputId = 'bundle-option-' . $block->escapeHtmlAttr($_option->getId()) ?>
13-
<?php $inputName = 'bundle_option[' . $block->escapeHtmlAttr($_option->getId()) . ']' ?>
16+
<?php $inputClass = 'checkbox product bundle option bundle-option-' . $escaper->escapeHtmlAttr($_option->getId()) ?>
17+
<?php $inputId = 'bundle-option-' . $escaper->escapeHtmlAttr($_option->getId()) ?>
18+
<?php $inputName = 'bundle_option[' . $escaper->escapeHtmlAttr($_option->getId()) . ']' ?>
1419
<?php $dataValidation = 'data-validate="{\'validate-one-required-by-name\':\'input[name^=&quot;bundle_option[' .
15-
$block->escapeHtmlAttr($_option->getId()) . ']&quot;]:checked\'}"' ?>
20+
$escaper->escapeHtmlAttr($_option->getId()) . ']&quot;]:checked\'}"' ?>
1621

1722
<div class="field option <?= ($_option->getRequired()) ? ' required': '' ?>">
1823
<label class="label">
19-
<span><?= $block->escapeHtml($_option->getTitle()) ?></span>
24+
<span><?= $escaper->escapeHtml($_option->getTitle()) ?></span>
2025
</label>
2126
<div class="control">
2227
<div class="nested options-list">
2328
<?php if ($block->showSingle()): ?>
2429
<?= /* @noEscape */ $block->getSelectionQtyTitlePrice($_selections[0]) ?>
2530
<?= /* @noEscape */ $block->getTierPriceRenderer()->renderTierPrice($_selections[0]) ?>
2631
<input type="hidden"
27-
class="bundle-option-<?= $block->escapeHtmlAttr($_option->getId()) ?> product bundle option"
28-
name="bundle_option[<?= $block->escapeHtml($_option->getId()) ?>]"
29-
value="<?= $block->escapeHtmlAttr($_selections[0]->getSelectionId()) ?>"/>
32+
class="bundle-option-<?= $escaper->escapeHtmlAttr($_option->getId()) ?> product bundle option"
33+
name="bundle_option[<?= $escaper->escapeHtml($_option->getId()) ?>]"
34+
value="<?= $escaper->escapeHtmlAttr($_selections[0]->getSelectionId()) ?>"/>
3035
<?php else: ?>
3136
<?php foreach ($_selections as $selection): ?>
3237
<?php $sectionId = $selection->getSelectionId() ?>
3338
<div class="field choice">
3439
<input class="<?=/* @noEscape */ $inputClass ?> change-container-classname"
35-
id="<?=/* @noEscape */ $inputId . '-' . $block->escapeHtmlAttr($sectionId)?>"
36-
type="checkbox"
37-
<?php if ($_option->getRequired()): ?>
38-
<?= /* @noEscape */ $dataValidation ?>
39-
<?php endif;?>
40-
name="<?=/* @noEscape */ $inputName .'['. $block->escapeHtmlAttr($sectionId)?>]"
41-
data-selector="<?= /* @noEscape */ $inputName.'['.$block->escapeHtmlAttr($sectionId)?>]"
42-
<?php if ($block->isSelected($selection)): ?>
43-
<?= ' checked="checked"' ?>
44-
<?php endif; ?>
45-
<?php if (!$selection->isSaleable()): ?>
46-
<?= ' disabled="disabled"' ?>
47-
<?php endif; ?>
48-
value="<?= $block->escapeHtmlAttr($sectionId) ?>"
49-
data-errors-message-box="#validation-message-box"/>
40+
id="<?=/* @noEscape */ $inputId . '-' . $escaper->escapeHtmlAttr($sectionId)?>"
41+
type="checkbox"
42+
<?php if ($_option->getRequired()): ?>
43+
<?= /* @noEscape */ $dataValidation ?>
44+
<?php endif;?>
45+
name="<?=/* @noEscape */ $inputName .'['. $escaper->escapeHtmlAttr($sectionId)?>]"
46+
data-selector="<?= /* @noEscape */ $inputName.'['.$escaper->escapeHtmlAttr($sectionId)?>]"
47+
<?php if ($block->isSelected($selection)): ?>
48+
<?= ' checked="checked"' ?>
49+
<?php endif; ?>
50+
<?php if (!$selection->isSaleable()): ?>
51+
<?= ' disabled="disabled"' ?>
52+
<?php endif; ?>
53+
value="<?= $escaper->escapeHtmlAttr($sectionId) ?>"
54+
data-errors-msg-box="#validation-message-box-<?=$escaper->escapeHtmlAttr($_option->getId())?>"/>
5055
<label class="label"
51-
for="<?= /* @noEscape */ $inputId . '-' . $block->escapeHtmlAttr($sectionId) ?>">
56+
for="<?= /* @noEscape */ $inputId . '-' . $escaper->escapeHtmlAttr($sectionId) ?>">
5257
<span><?= /* @noEscape */ $block->getSelectionQtyTitlePrice($selection) ?></span>
5358
<br/>
5459
<?= /* @noEscape */ $block->getTierPriceRenderer()->renderTierPrice($selection) ?>
5560
</label>
5661
</div>
62+
5763
<?php endforeach; ?>
58-
<div id="bundle-option-<?= $block->escapeHtmlAttr($_option->getId()) ?>-container"></div>
59-
<div id="validation-message-box"></div>
6064
<?php endif; ?>
6165
</div>
66+
<div id="bundle-option-<?= $escaper->escapeHtmlAttr($_option->getId()) ?>-container"></div>
67+
<div id="validation-message-box-<?= $escaper->escapeHtmlAttr($_option->getId()) ?>"></div>
6268
</div>
6369
</div>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
define([
2+
'jquery',
3+
'jquery-ui-modules/widget'
4+
], function ($) {
5+
'use strict';
6+
var enhancedMageValidation = {
7+
/**
8+
* @param {*} error
9+
* @param {*} element
10+
*/
11+
options: {
12+
errorPlacement: function (error, element) {
13+
var errorPlacement = element,
14+
fieldWrapper,messageBox;
15+
16+
// logic for date-picker error placement
17+
if (element.hasClass('_has-datepicker')) {
18+
errorPlacement = element.siblings('button');
19+
}
20+
// logic for field wrapper
21+
fieldWrapper = element.closest('.addon');
22+
23+
if (fieldWrapper.length) {
24+
errorPlacement = fieldWrapper.after(error);
25+
}
26+
//logic for checkboxes/radio
27+
if (element.is(':checkbox') || element.is(':radio')) {
28+
errorPlacement = element.parents('.control').children().last();
29+
30+
//fallback if group does not have .control parent
31+
if (!errorPlacement.length) {
32+
errorPlacement = element.siblings('label').last();
33+
}
34+
}
35+
if (element.attr('data-errors-msg-box')) {
36+
messageBox = $(element.attr('data-errors-msg-box'));
37+
messageBox.html(error);
38+
return;
39+
}
40+
//logic for control with tooltip
41+
if (element.siblings('.tooltip').length) {
42+
errorPlacement = element.siblings('.tooltip');
43+
}
44+
//logic for select with tooltip in after element
45+
if (element.next().find('.tooltip').length) {
46+
errorPlacement = element.next();
47+
}
48+
errorPlacement.after(error);
49+
}
50+
51+
}
52+
};
53+
54+
return function (mageValidation) {
55+
$.widget('mage.validation', mageValidation, enhancedMageValidation);
56+
return $.mage.validation;
57+
};
58+
});

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
<arguments>
1313
<argument name="fileName" defaultValue="magento-logo" type="string"/>
1414
</arguments>
15-
<seeElement selector="{{StorefrontProductMediaSection.productImageActive(fileName)}}" stepKey="seeActiveImageDefault"/>
15+
<waitForElementVisible selector="{{StorefrontProductMediaSection.productImageActive(fileName)}}" stepKey="seeActiveImageDefault"/>
1616
</actionGroup>
1717
</actionGroups>

0 commit comments

Comments
 (0)