Skip to content

Commit 711b09c

Browse files
authored
Merge pull request #6141 from magento-tsg-csl3/2.4-develop-pr40
[TSG-CSL3] For 2.4 (pr40)
2 parents 6783060 + b320212 commit 711b09c

File tree

12 files changed

+177
-33
lines changed

12 files changed

+177
-33
lines changed

app/code/Magento/Checkout/Model/ShippingInformationManagement.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,11 @@ public function saveAddressInformation(
209209
if (!$quote->getIsVirtual()
210210
&& !$shippingAddress->getShippingRateByCode($shippingAddress->getShippingMethod())
211211
) {
212-
throw new NoSuchEntityException(
212+
$errorMessage = $methodCode ?
213213
__('Carrier with such method not found: %1, %2', $carrierCode, $methodCode)
214+
: __('The shipping method is missing. Select the shipping method and try again.');
215+
throw new NoSuchEntityException(
216+
$errorMessage
214217
);
215218
}
216219

app/code/Magento/Checkout/Test/Mftf/Data/ConfigData.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@
8181
<data key="label">All Allowed Countries</data>
8282
<data key="value">0</data>
8383
</entity>
84+
<entity name="EnableFlatRateShowMethodNoApplicableConfigData">
85+
<data key="path">carriers/flatrate/showmethod</data>
86+
<data key="scope">carriers</data>
87+
<data key="scope_id">1</data>
88+
<data key="label">Show Method if Not Applicable</data>
89+
<data key="value">1</data>
90+
</entity>
8491
<entity name="DisableFlatRateConfigData">
8592
<data key="path">carriers/flatrate/active</data>
8693
<data key="scope">carriers</data>

app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingMethodsSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@
2020
<element name="shippingMethodLoader" type="button" selector="//div[contains(@class, 'checkout-shipping-method')]/following-sibling::div[contains(@class, 'loading-mask')]"/>
2121
<element name="freeShippingShippingMethod" type="input" selector="#s_method_freeshipping_freeshipping" timeout="30"/>
2222
<element name="noQuotesMsg" type="text" selector="#checkout-step-shipping_method div"/>
23+
<element name="price" type="text" selector="//*[@id='checkout-shipping-method-load']//td[@class='col col-price']"/>
2324
</section>
2425
</sections>
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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="StorefrontCheckoutForShowShippingMethodNoApplicableTest">
12+
<annotations>
13+
<stories value="Checkout for not applicable shipping method"/>
14+
<title value="Storefront checkout for not applicable shipping method test"/>
15+
<description value="Checkout flow if shipping rates are not applicable"/>
16+
<severity value="AVERAGE"/>
17+
<testCaseId value="MC-37420"/>
18+
<group value="checkout"/>
19+
</annotations>
20+
<before>
21+
<!-- Create simple product -->
22+
<createData entity="SimpleProduct2" stepKey="createProduct"/>
23+
<!-- Enable flat rate shipping to specific country - Afghanistan -->
24+
<magentoCLI command="config:set {{EnableFlatRateConfigData.path}} {{EnableFlatRateConfigData.value}}" stepKey="enableFlatRate"/>
25+
<magentoCLI command="config:set {{EnableFlatRateToSpecificCountriesConfigData.path}} {{EnableFlatRateToSpecificCountriesConfigData.value}}" stepKey="allowFlatRateSpecificCountries"/>
26+
<magentoCLI command="config:set {{EnableFlatRateToAfghanistanConfigData.path}} {{EnableFlatRateToAfghanistanConfigData.value}}" stepKey="enableFlatRateToAfghanistan"/>
27+
<!-- Enable Show Method if Not Applicable-->
28+
<magentoCLI command="config:set {{EnableFlatRateShowMethodNoApplicableConfigData.path}} {{EnableFlatRateShowMethodNoApplicableConfigData.value}}" stepKey="enableShowMethodNoApplicable"/>
29+
<!-- Create Customer with filled Shipping & Billing Address -->
30+
<createData entity="CustomerEntityOne" stepKey="createCustomer"/>
31+
</before>
32+
<after>
33+
<actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutFromStorefront"/>
34+
<deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/>
35+
<magentoCLI command="config:set {{EnableFlatRateToAllAllowedCountriesConfigData.path}} {{EnableFlatRateToAllAllowedCountriesConfigData.value}}" stepKey="allowFlatRateToAllCountries"/>
36+
<magentoCLI command="config:set {{EnableFlatRateShowMethodNoApplicableConfigData.path}} 0" stepKey="disableShowMethodNoApplicable"/>
37+
<!-- Delete product -->
38+
<deleteData createDataKey="createProduct" stepKey="deleteProduct"/>
39+
</after>
40+
<!-- Login with created Customer -->
41+
<actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginAsCustomer">
42+
<argument name="Customer" value="$$createCustomer$$"/>
43+
</actionGroup>
44+
<!-- Add product to cart -->
45+
<actionGroup ref="OpenStoreFrontProductPageActionGroup" stepKey="openProductPage">
46+
<argument name="productUrlKey" value="$$createProduct.custom_attributes[url_key]$$"/>
47+
</actionGroup>
48+
<actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="addProductToCart">
49+
<argument name="product" value="$$createProduct$$"/>
50+
<argument name="productCount" value="1"/>
51+
</actionGroup>
52+
<!-- Go to checkout page -->
53+
<actionGroup ref="OpenStoreFrontCheckoutShippingPageActionGroup" stepKey="openCheckoutShippingPage"/>
54+
<!-- Assert shipping price for US > California -->
55+
<dontSeeElement selector="{{CheckoutShippingMethodsSection.price}}" stepKey="dontSeePrice"/>
56+
<!-- Assert Next button is available -->
57+
<seeElement selector="{{CheckoutShippingMethodsSection.next}}" stepKey="seeNextButton"/>
58+
<click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickNextButton"/>
59+
<!-- Assert order cannot be placed and error message will shown. -->
60+
<waitForPageLoad stepKey="waitForError"/>
61+
<see stepKey="seeShippingMethodError" userInput="The shipping method is missing. Select the shipping method and try again."/>
62+
</test>
63+
</tests>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,4 @@ Payment,Payment
185185
"Close","Close"
186186
"Show Cross-sell Items in the Shopping Cart","Show Cross-sell Items in the Shopping Cart"
187187
"You added %1 to your <a href=""%2"">shopping cart</a>.","You added %1 to your <a href=""%2"">shopping cart</a>."
188+
"The shipping method is missing. Select the shipping method and try again.","The shipping method is missing. Select the shipping method and try again."

app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,12 @@ define([
299299
this.source.set('params.invalid', false);
300300
this.triggerShippingDataValidateEvent();
301301

302+
if (!quote.shippingMethod()['method_code']) {
303+
this.errorValidationMessage(
304+
$t('The shipping method is missing. Select the shipping method and try again.')
305+
);
306+
}
307+
302308
if (emailValidationResult &&
303309
this.source.get('params.invalid') ||
304310
!quote.shippingMethod()['method_code'] ||

app/code/Magento/Checkout/view/frontend/web/template/shipping-address/shipping-method-item.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
attr="'aria-labelledby': 'label_method_' + method.method_code + '_' + method.carrier_code + ' ' + 'label_carrier_' + method.method_code + '_' + method.carrier_code,
1616
'checked': element.rates().length == 1 || element.isSelected" />
1717
</td>
18+
<!-- ko ifnot: (method.error_message) -->
1819
<td class="col col-price">
1920
<each args="element.getRegion('price')" render="" />
2021
</td>
22+
<!-- /ko -->
2123
<td class="col col-method"
2224
attr="'id': 'label_method_' + method.method_code + '_' + method.carrier_code"
2325
text="method.method_title" />

dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_products.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
$product = $objectManager->create(Product::class);
4545
$productId = array_shift($productIds);
4646
$product->setTypeId(Type::TYPE_SIMPLE)
47-
->setId($productId)
4847
->setAttributeSetId($attributeSetId)
4948
->setWebsiteIds([1])
5049
->setName('Configurable Option' . $option->getLabel())
@@ -84,7 +83,6 @@
8483
$product->setExtensionAttributes($extensionConfigurableAttributes);
8584

8685
$product->setTypeId(Configurable::TYPE_CODE)
87-
->setId(1)
8886
->setAttributeSetId($attributeSetId)
8987
->setWebsiteIds([1])
9088
->setName('Configurable Product')
@@ -110,7 +108,6 @@
110108
$product = $objectManager->create(Product::class);
111109
$productId = array_shift($productIds);
112110
$product->setTypeId(Type::TYPE_SIMPLE)
113-
->setId($productId)
114111
->setAttributeSetId($attributeSetId)
115112
->setWebsiteIds([1])
116113
->setName('Configurable Option' . $option->getLabel())
@@ -155,7 +152,6 @@
155152
$product->setExtensionAttributes($extensionConfigurableAttributes);
156153

157154
$product->setTypeId(Configurable::TYPE_CODE)
158-
->setId(11)
159155
->setAttributeSetId($attributeSetId)
160156
->setWebsiteIds([1])
161157
->setName('Configurable Product 12345')

dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/quote_with_configurable_product_last_variation.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
$quote = $objectManager->create(\Magento\Quote\Model\Quote::class);
1515
/** @var ProductRepositoryInterface $productRepository */
1616
$productRepository = $objectManager->create(ProductRepositoryInterface::class);
17-
$product = $productRepository->getById(10);
17+
$product = $productRepository->get('simple_10');
1818
$product->setStockData(['use_config_manage_stock' => 1, 'qty' => 1, 'is_qty_decimal' => 0, 'is_in_stock' => 1]);
1919
$productRepository->save($product);
2020

21-
$product = $productRepository->getById(20);
21+
$product = $productRepository->get('simple_20');
2222
$product->setStockData(['use_config_manage_stock' => 1, 'qty' => 0, 'is_qty_decimal' => 0, 'is_in_stock' => 0]);
2323
$productRepository->save($product);
2424

dev/tests/integration/testsuite/Magento/Multishipping/Fixtures/quote_with_configurable_product.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
$objectManager = Bootstrap::getObjectManager();
2525
/** @var ProductRepositoryInterface $productRepository */
2626
$productRepository = $objectManager->create(ProductRepositoryInterface::class);
27-
$product = $productRepository->getById(10);
27+
$product = $productRepository->get('simple_10');
2828
$product->setStockData(['use_config_manage_stock' => 1, 'qty' => 4, 'is_qty_decimal' => 0, 'is_in_stock' => 1]);
2929
$productRepository->save($product);
3030

lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ class Timezone implements TimezoneInterface
3030
\IntlDateFormatter::SHORT,
3131
];
3232

33+
/**
34+
* @var array
35+
*/
36+
private $dateFormatterCache = [];
37+
3338
/**
3439
* @var string
3540
*/
@@ -174,16 +179,9 @@ public function date($date = null, $locale = null, $useTimezone = true, $include
174179
case ($date instanceof \DateTimeImmutable):
175180
return new \DateTime($date->format('Y-m-d H:i:s'), $date->getTimezone());
176181
case (!is_numeric($date)):
177-
$timeType = $includeTime ? \IntlDateFormatter::SHORT : \IntlDateFormatter::NONE;
178-
$formatter = new \IntlDateFormatter(
179-
$locale,
180-
\IntlDateFormatter::MEDIUM,
181-
$timeType,
182-
new \DateTimeZone($timezone)
183-
);
184-
185182
$date = $this->appendTimeIfNeeded($date, $includeTime, $timezone, $locale);
186-
$date = $formatter->parse($date) ?: (new \DateTime($date))->getTimestamp();
183+
$date = $this->parseLocaleDate($date, $locale, $timezone, $includeTime)
184+
?: (new \DateTime($date))->getTimestamp();
187185
break;
188186
}
189187

@@ -343,33 +341,77 @@ public function convertConfigTimeToUtc($date, $format = 'Y-m-d H:i:s')
343341
private function appendTimeIfNeeded($date, $includeTime, $timezone, $locale)
344342
{
345343
if ($includeTime && !preg_match('/\d{1}:\d{2}/', $date)) {
346-
347-
$formatterWithoutHour = new \IntlDateFormatter(
348-
$locale,
349-
\IntlDateFormatter::MEDIUM,
350-
\IntlDateFormatter::NONE,
351-
new \DateTimeZone($timezone)
352-
);
353-
$convertedDate = $formatterWithoutHour->parse($date);
354-
344+
$convertedDate = $this->parseLocaleDate($date, $locale, $timezone, false);
355345
if (!$convertedDate) {
356346
throw new LocalizedException(
357347
new Phrase(
358348
'Could not append time to DateTime'
359349
)
360350
);
361-
362351
}
363352

364-
$formatterWithHour = new \IntlDateFormatter(
353+
$formatterWithHour = $this->getDateFormatter(
365354
$locale,
355+
$timezone,
366356
\IntlDateFormatter::MEDIUM,
367-
\IntlDateFormatter::SHORT,
368-
new \DateTimeZone($timezone)
357+
\IntlDateFormatter::SHORT
369358
);
370-
371359
$date = $formatterWithHour->format($convertedDate);
372360
}
373361
return $date;
374362
}
363+
364+
/**
365+
* Parse date by locale format through IntlDateFormatter
366+
*
367+
* @param string $date
368+
* @param string $locale
369+
* @param string $timeZone
370+
* @param bool $includeTime
371+
* @return int|null Timestamp of date
372+
*/
373+
private function parseLocaleDate(string $date, string $locale, string $timeZone, bool $includeTime): ?int
374+
{
375+
$allowedStyles = [\IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT];
376+
$timeStyle = $includeTime ? \IntlDateFormatter::SHORT : \IntlDateFormatter::NONE;
377+
378+
/**
379+
* Try to parse date with different styles
380+
*/
381+
foreach ($allowedStyles as $style) {
382+
$formatter = $this->getDateFormatter($locale, $timeZone, $style, $timeStyle);
383+
$timeStamp = $formatter->parse($date);
384+
if ($timeStamp) {
385+
return $timeStamp;
386+
}
387+
}
388+
389+
return null;
390+
}
391+
392+
/**
393+
* Get date formatter for locale
394+
*
395+
* @param string $locale
396+
* @param string $timeZone
397+
* @param int $style
398+
* @param int $timeStyle
399+
* @return \IntlDateFormatter
400+
*/
401+
private function getDateFormatter(string $locale, string $timeZone, int $style, int $timeStyle): \IntlDateFormatter
402+
{
403+
$cacheKey = "{$locale}_{$timeZone}_{$style}_{$timeStyle}";
404+
if (isset($this->dateFormatterCache[$cacheKey])) {
405+
return $this->dateFormatterCache[$cacheKey];
406+
}
407+
408+
$this->dateFormatterCache[$cacheKey] = new \IntlDateFormatter(
409+
$locale,
410+
$style,
411+
$timeStyle,
412+
new \DateTimeZone($timeZone)
413+
);
414+
415+
return $this->dateFormatterCache[$cacheKey];
416+
}
375417
}

lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,12 @@ public function testDateIncludeTime($date, $locale, $includeTime, $expectedTimes
101101

102102
/** @var \DateTime $dateTime */
103103
$dateTime = $timezone->date($date, $locale, true, $includeTime);
104-
$this->assertEquals($expectedTimestamp, $dateTime->getTimestamp());
104+
if (is_numeric($expectedTimestamp)) {
105+
$this->assertEquals($expectedTimestamp, $dateTime->getTimestamp());
106+
} else {
107+
$format = $includeTime ? DateTime::DATETIME_PHP_FORMAT : DateTime::DATE_PHP_FORMAT;
108+
$this->assertEquals($expectedTimestamp, date($format, $dateTime->getTimestamp()));
109+
}
105110
}
106111

107112
/**
@@ -151,7 +156,25 @@ public function dateIncludeTimeDataProvider(): array
151156
'el_GR', // locale
152157
false, // include time
153158
1635570000 // expected timestamp
154-
]
159+
],
160+
'Parse Saudi Arabia date without time' => [
161+
'31‏/8‏/2020 02020',
162+
'ar_SA',
163+
false,
164+
'2020-08-31'
165+
],
166+
'Parse date in short style with long year 1999' => [
167+
'9/11/1999',
168+
'en_US',
169+
false,
170+
'1999-09-11'
171+
],
172+
'Parse date in short style with long year 2099' => [
173+
'9/2/2099',
174+
'en_US',
175+
false,
176+
'2099-09-02'
177+
],
155178
];
156179
}
157180

0 commit comments

Comments
 (0)