Skip to content

Commit bc7f065

Browse files
committed
Merge remote-tracking branch 'origin/2.4-develop' into MC-35725
2 parents a391a9f + 2c173c9 commit bc7f065

File tree

33 files changed

+699
-48
lines changed

33 files changed

+699
-48
lines changed

app/code/Magento/Backend/App/Area/FrontNameResolver.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,13 @@ public function isHostBackend()
123123
if ($this->scopeConfig->getValue(self::XML_PATH_USE_CUSTOM_ADMIN_URL, ScopeInterface::SCOPE_STORE)) {
124124
$backendUrl = $this->scopeConfig->getValue(self::XML_PATH_CUSTOM_ADMIN_URL, ScopeInterface::SCOPE_STORE);
125125
} else {
126-
$backendUrl = $this->scopeConfig->getValue(Store::XML_PATH_UNSECURE_BASE_URL, ScopeInterface::SCOPE_STORE);
126+
$backendUrl = $this->config->getValue(Store::XML_PATH_UNSECURE_BASE_URL);
127+
if ($backendUrl === null) {
128+
$backendUrl = $this->scopeConfig->getValue(
129+
Store::XML_PATH_UNSECURE_BASE_URL,
130+
ScopeInterface::SCOPE_STORE
131+
);
132+
}
127133
}
128134
$host = $this->request->getServer('HTTP_HOST', '');
129135
return stripos($this->getHostWithPort($backendUrl), (string) $host) !== false;

app/code/Magento/Backend/Block/Widget/Button.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
*/
66
namespace Magento\Backend\Block\Widget;
77

8+
use Magento\Backend\Block\Template\Context;
89
use Magento\Framework\App\ObjectManager;
910
use Magento\Framework\Math\Random;
10-
use Magento\Backend\Block\Template\Context;
1111
use Magento\Framework\View\Helper\SecureHtmlRenderer;
1212

1313
/**
@@ -125,6 +125,9 @@ protected function _prepareAttributes($title, $classes, $disabled)
125125
'value' => $this->getValue(),
126126
'disabled' => $disabled,
127127
];
128+
if ($this->hasData('onclick_attribute')) {
129+
$attributes['onclick'] = $this->getData('onclick_attribute');
130+
}
128131
if ($this->hasData('backend_button_widget_hook_id')) {
129132
$attributes['backend-button-widget-hook-id'] = $this->getData('backend_button_widget_hook_id');
130133
}

app/code/Magento/Backend/Test/Unit/Block/Widget/ButtonTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,16 @@ public function getAttributesHtmlDataProvider()
9494
]
9595
];
9696
}
97+
98+
/**
99+
* Verifies ability of adding button onclick attribute
100+
*
101+
* @return void
102+
*/
103+
public function testOnClickAttribute(): void
104+
{
105+
$this->_blockMock->setData(['onclick_attribute' => 'value']);
106+
$attributes = $this->_blockMock->getAttributesHtml();
107+
$this->assertStringContainsString('onclick', $attributes);
108+
}
97109
}

app/code/Magento/Catalog/Model/Product/Type/Price.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ public function getTierPrices($product)
379379
if (array_key_exists('website_price', $price)) {
380380
$value = $price['website_price'];
381381
} else {
382-
$value = $price['price'];
382+
$value = $price['price'] ?? 0;
383383
}
384384
$tierPrice->setValue($value);
385385
$tierPrice->setQty($price['price_qty']);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
10+
<actionGroup name="AdminDeleteAllProductAttributesFilteredByCodeActionGroup">
11+
<annotations>
12+
<description>Open product attributes grid filter it by attribute code and delete all found attributes one by one.</description>
13+
</annotations>
14+
<arguments>
15+
<argument name="codeFilter" type="string" defaultValue="fake-code"/>
16+
</arguments>
17+
18+
<amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttributeGrid"/>
19+
<!-- It sometimes is loading too long for default 10s -->
20+
<waitForPageLoad time="60" stepKey="waitForPageFullyLoaded"/>
21+
<click selector="{{AdminProductAttributeGridSection.ResetFilter}}" stepKey="clearExistingFilters"/>
22+
<fillField selector="{{AdminProductAttributeGridSection.FilterByAttributeCode}}" userInput="{{codeFilter}}" stepKey="fillAttributeCodeFilterField"/>
23+
<click selector="{{AdminProductAttributeGridSection.Search}}" stepKey="applyGridFilter"/>
24+
<helper class="\Magento\Catalog\Test\Mftf\Helper\CatalogHelper" method="deleteAllProductAttributesOneByOne" stepKey="deleteAllProductAttributesOneByOne">
25+
<argument name="notEmptyRow">{{AdminDataGridTableSection.firstNotEmptyRow2}}</argument>
26+
<argument name="modalAcceptButton">{{AdminConfirmationModalSection.ok}}</argument>
27+
<argument name="deleteButton">{{AdminMainActionsSection.delete}}</argument>
28+
<argument name="successMessageContainer">{{AdminMessagesSection.success}}</argument>
29+
<argument name="successMessage">You deleted the product attribute.</argument>
30+
</helper>
31+
<waitForElementVisible selector="{{AdminDataGridTableSection.dataGridEmpty}}" stepKey="waitDataGridEmptyMessageAppears"/>
32+
<see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="assertDataGridEmptyMessage"/>
33+
<click selector="{{AdminProductAttributeGridSection.ResetFilter}}" stepKey="clearExistingFiltersAgain"/>
34+
</actionGroup>
35+
</actionGroups>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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\Catalog\Test\Mftf\Helper;
9+
10+
use Facebook\WebDriver\Remote\RemoteWebDriver as FacebookWebDriver;
11+
use Facebook\WebDriver\WebDriverBy;
12+
use Magento\FunctionalTestingFramework\Helper\Helper;
13+
use Magento\FunctionalTestingFramework\Module\MagentoWebDriver;
14+
15+
/**
16+
* Class for MFTF helpers for Catalog module.
17+
*/
18+
class CatalogHelper extends Helper
19+
{
20+
/**
21+
* Delete all product attributes one by one.
22+
*
23+
* @param string $notEmptyRow
24+
* @param string $modalAcceptButton
25+
* @param string $deleteButton
26+
* @param string $successMessageContainer
27+
* @param string $successMessage
28+
* @retrun void
29+
*/
30+
public function deleteAllProductAttributesOneByOne(
31+
string $notEmptyRow,
32+
string $modalAcceptButton,
33+
string $deleteButton,
34+
string $successMessageContainer,
35+
string $successMessage
36+
): void {
37+
try {
38+
/** @var MagentoWebDriver $webDriver */
39+
$magentoWebDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver');
40+
/** @var FacebookWebDriver $webDriver */
41+
$webDriver = $magentoWebDriver->webDriver;
42+
$gridRows = $webDriver->findElements(WebDriverBy::cssSelector($notEmptyRow));
43+
while (!empty($gridRows)) {
44+
$gridRows[0]->click();
45+
$magentoWebDriver->waitForPageLoad(30);
46+
$magentoWebDriver->click($deleteButton);
47+
$magentoWebDriver->waitForPageLoad(30);
48+
$magentoWebDriver->waitForElementVisible($modalAcceptButton);
49+
$magentoWebDriver->click($modalAcceptButton);
50+
$magentoWebDriver->waitForPageLoad(60);
51+
$magentoWebDriver->waitForElementVisible($successMessageContainer);
52+
$magentoWebDriver->see($successMessage, $successMessageContainer);
53+
$gridRows = $webDriver->findElements(WebDriverBy::cssSelector($notEmptyRow));
54+
}
55+
} catch (\Exception $e) {
56+
$this->fail($e->getMessage());
57+
}
58+
}
59+
}

app/code/Magento/Catalog/Test/Unit/Model/Product/Type/PriceTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,4 +263,40 @@ function () {
263263
);
264264
}
265265
}
266+
267+
/**
268+
* Get tier price with percent value type
269+
*
270+
* @return void
271+
*/
272+
public function testGetPricesWithPercentType(): void
273+
{
274+
$tierPrices = [
275+
0 => [
276+
'record_id' => 0,
277+
'cust_group' => 3200,
278+
'price_qty' => 3,
279+
'website_id' => 0,
280+
'value_type' => 'percent',
281+
'percentage_value' => 10,
282+
],
283+
];
284+
$this->product->setData('tier_price', $tierPrices);
285+
$this->tpFactory->expects($this->any())
286+
->method('create')
287+
->willReturnCallback(
288+
function () {
289+
return $this->objectManagerHelper->getObject(TierPrice::class);
290+
}
291+
);
292+
$tierPriceExtensionMock = $this->getMockBuilder(ProductTierPriceExtensionInterface::class)
293+
->onlyMethods(['getPercentageValue', 'setPercentageValue'])
294+
->getMockForAbstractClass();
295+
$tierPriceExtensionMock->method('getPercentageValue')
296+
->willReturn(50);
297+
$this->tierPriceExtensionFactoryMock->method('create')
298+
->willReturn($tierPriceExtensionMock);
299+
300+
$this->assertInstanceOf(TierPrice::class, $this->model->getTierPrices($this->product)[0]);
301+
}
266302
}

app/code/Magento/CatalogGraphQl/Plugin/Search/Request/ConfigReader.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ private function getSearchableAttributes(): array
106106
$productAttributes->addFieldToFilter(
107107
['is_searchable', 'is_visible_in_advanced_search', 'is_filterable', 'is_filterable_in_search'],
108108
[1, 1, [1, 2], 1]
109+
)->setOrder(
110+
'position',
111+
'ASC'
109112
);
110113

111114
/** @var Attribute $attribute */

app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<div if="isAddressDetailsVisible() && currentBillingAddress()" class="billing-address-details">
88
<text args="currentBillingAddress().prefix"/> <text args="currentBillingAddress().firstname"/> <text args="currentBillingAddress().middlename"/>
99
<text args="currentBillingAddress().lastname"/> <text args="currentBillingAddress().suffix"/><br/>
10-
<text args="_.values(currentBillingAddress().street).join(', ')"/><br/>
10+
<text args="currentBillingAddress().street.join(', ')"/><br/>
1111
<text args="currentBillingAddress().city "/>, <span text="currentBillingAddress().region"></span> <text args="currentBillingAddress().postcode"/><br/>
1212
<text args="getCountryName(currentBillingAddress().countryId)"/><br/>
1313
<a if="currentBillingAddress().telephone" attr="'href': 'tel:' + currentBillingAddress().telephone" text="currentBillingAddress().telephone"></a><br/>

app/code/Magento/Persistent/Observer/EmulateCustomerObserver.php

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
namespace Magento\Persistent\Observer;
77

88
use Magento\Framework\Event\ObserverInterface;
9+
use Magento\Framework\Exception\NoSuchEntityException;
910

1011
/**
1112
* Class EmulateCustomer
@@ -86,9 +87,9 @@ public function execute(\Magento\Framework\Event\Observer $observer)
8687
/** @var \Magento\Customer\Api\Data\CustomerInterface $customer */
8788
$customer = $this->customerRepository->getById($this->_persistentSession->getSession()->getCustomerId());
8889
if ($defaultShipping = $customer->getDefaultShipping()) {
89-
/** @var \Magento\Customer\Model\Data\Address $address */
90-
$address = $this->addressRepository->getById($defaultShipping);
91-
if ($address) {
90+
$address = $this->getCustomerAddressById((int) $defaultShipping);
91+
92+
if ($address !== null) {
9293
$this->_customerSession->setDefaultTaxShippingAddress(
9394
[
9495
'country_id' => $address->getCountryId(),
@@ -102,8 +103,9 @@ public function execute(\Magento\Framework\Event\Observer $observer)
102103
}
103104

104105
if ($defaultBilling = $customer->getDefaultBilling()) {
105-
$address = $this->addressRepository->getById($defaultBilling);
106-
if ($address) {
106+
$address = $this->getCustomerAddressById((int) $defaultBilling);
107+
108+
if ($address !== null) {
107109
$this->_customerSession->setDefaultTaxBillingAddress([
108110
'country_id' => $address->getCountryId(),
109111
'region_id' => $address->getRegion() ? $address->getRegionId() : null,
@@ -118,4 +120,19 @@ public function execute(\Magento\Framework\Event\Observer $observer)
118120
}
119121
return $this;
120122
}
123+
124+
/**
125+
* Returns customer address by id
126+
*
127+
* @param int $addressId
128+
* @return \Magento\Customer\Api\Data\AddressInterface|null
129+
*/
130+
private function getCustomerAddressById(int $addressId)
131+
{
132+
try {
133+
return $this->addressRepository->getById($addressId);
134+
} catch (NoSuchEntityException $exception) {
135+
return null;
136+
}
137+
}
121138
}

app/code/Magento/Persistent/Test/Unit/Observer/EmulateCustomerObserverTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,14 @@ public function testExecuteWhenSessionPersistAndCustomerNotLoggedIn()
131131
$customerMock
132132
->expects($this->once())
133133
->method('getDefaultShipping')
134-
->willReturn('shippingId');
134+
->willReturn(12345);
135135
$customerMock
136136
->expects($this->once())
137137
->method('getDefaultBilling')
138-
->willReturn('billingId');
138+
->willReturn(12346);
139139
$valueMap = [
140-
['shippingId', $defaultShippingAddressMock],
141-
['billingId', $defaultBillingAddressMock]
140+
[12345, $defaultShippingAddressMock],
141+
[12346, $defaultBillingAddressMock]
142142
];
143143
$this->addressRepositoryMock->expects($this->any())->method('getById')->willReturnMap($valueMap);
144144
$this->customerSessionMock
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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\Quote\Model\Quote\Plugin;
9+
10+
use Magento\Quote\Model\Quote;
11+
use Magento\Store\Model\StoreManagerInterface;
12+
13+
/**
14+
* Updates quote store id.
15+
*/
16+
class UpdateQuoteStoreId
17+
{
18+
/**
19+
* @var StoreManagerInterface
20+
*/
21+
private $storeManager;
22+
23+
/**
24+
* @param StoreManagerInterface $storeManager
25+
*/
26+
public function __construct(
27+
StoreManagerInterface $storeManager
28+
) {
29+
$this->storeManager = $storeManager;
30+
}
31+
32+
/**
33+
* Update store id in requested quote by store id from request.
34+
*
35+
* @param Quote $subject
36+
* @param Quote $result
37+
* @return Quote
38+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
39+
*/
40+
public function afterLoadByIdWithoutStore(Quote $subject, Quote $result): Quote
41+
{
42+
$storeId = $this->storeManager->getStore()
43+
->getId() ?: $this->storeManager->getDefaultStoreView()
44+
->getId();
45+
$result->setStoreId($storeId);
46+
47+
return $result;
48+
}
49+
}

app/code/Magento/Quote/etc/webapi_rest/di.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,7 @@
1616
<type name="Magento\Quote\Api\GuestCartItemRepositoryInterface">
1717
<plugin name="updateCartIdFromRequest" type="Magento\Quote\Plugin\UpdateCartId" />
1818
</type>
19+
<type name="Magento\Quote\Model\Quote">
20+
<plugin name="updateQuoteStoreId" type="Magento\Quote\Model\Quote\Plugin\UpdateQuoteStoreId" />
21+
</type>
1922
</config>

app/code/Magento/Quote/etc/webapi_soap/di.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,7 @@
1313
<plugin name="accessControl" type="Magento\Quote\Model\QuoteRepository\Plugin\AccessChangeQuoteControl" />
1414
<plugin name="authorization" type="Magento\Quote\Model\QuoteRepository\Plugin\Authorization" />
1515
</type>
16+
<type name="Magento\Quote\Model\Quote">
17+
<plugin name="updateQuoteStoreId" type="Magento\Quote\Model\Quote\Plugin\UpdateQuoteStoreId" />
18+
</type>
1619
</config>

app/code/Magento/Sales/Test/Mftf/Test/AdminSaveInAddressBookCheckboxStateTest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
<actionGroup ref="AddSimpleProductToOrderActionGroup" stepKey="addSimpleProductToOrder">
4848
<argument name="product" value="$$createSimpleProduct$$"/>
4949
</actionGroup>
50+
<!-- By default checkbox 'Add to address book' must be unchecked -->
51+
<dontSeeCheckboxIsChecked selector="{{AdminOrderFormBillingAddressSection.SaveAddress}}" stepKey="checkBoxAddBillingAddressIsUnchecked"/>
5052
<!-- Just in case uncheck and check 'Same as Billing Address checkbox' -->
5153
<comment userInput="Just in case uncheck and check 'Same as Billing Address checkbox'" stepKey="uncheckAndCheckAgain"/>
5254
<uncheckOption selector="{{AdminOrderFormShippingAddressSection.SameAsBilling}}" stepKey="unCheckSameAsShippingAddressCheckbox"/>

app/code/Magento/Sales/i18n/en_US.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,3 +804,4 @@ If set YES Email field will be required during Admin order creation for new Cust
804804
"Please enter a coupon code!","Please enter a coupon code!"
805805
"Reorder is not available.","Reorder is not available."
806806
"The coupon code has been removed.","The coupon code has been removed."
807+
"Add to address book","Add to address book"

app/code/Magento/Sales/view/adminhtml/templates/order/create/form/address.phtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ endif; ?>
125125
<?php endif; ?>
126126
class="admin__control-checkbox"/>
127127
<label for="<?= $block->escapeHtmlAttr($block->getForm()->getHtmlIdPrefix()) ?>save_in_address_book"
128-
class="admin__field-label"><?= $block->escapeHtml(__('Save in address book')) ?></label>
128+
class="admin__field-label"><?= $block->escapeHtml(__('Add to address book')) ?></label>
129129
</div>
130130
</div>
131131
<?php $hideElement = 'address-' . ($block->getIsShipping() ? 'shipping' : 'billing') . '-overlay'; ?>

app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontAssertFixedCartDiscountAmountForBundleProductTest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
<before>
2121
<createData entity="SalesRuleNoCouponWithFixedDiscountWholeCart" stepKey="createSalesRule"/>
2222
<actionGroup ref="AdminCreateApiDynamicBundleProductAllOptionTypesActionGroup" stepKey="createBundleProduct"/>
23+
<actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindexCatalogInventory">
24+
<argument name="indices" value="cataloginventory_stock"/>
25+
</actionGroup>
2326
</before>
2427
<after>
2528
<deleteData createDataKey="createSalesRule" stepKey="deleteSalesRule"/>

app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@
2222
<element name="rowTemplateStrict" type="block" selector="//tbody/tr[td[*[text()[normalize-space()='{{text}}']]]]" parameterized="true" />
2323
<element name="rowTemplate" type="block" selector="//tbody/tr[td[*[contains(.,normalize-space('{{text}}'))]]]" parameterized="true" timeout="30" />
2424
<element name="firstNotEmptyRow" type="block" selector="table.data-grid tbody tr[data-role=row]:not(.data-grid-tr-no-data):nth-of-type(1)" timeout="30"/>
25+
<element name="firstNotEmptyRow2" type="block" selector="table.data-grid tbody tr:not(.data-grid-tr-no-data):nth-of-type(1)" timeout="30"/>
2526
</section>
2627
</sections>

0 commit comments

Comments
 (0)