diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js b/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js
index 5d0e32d6876a2..638cb19051db5 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js
@@ -44,6 +44,13 @@ define(
addressData.region.region_code = region['code'];
addressData.region.region = region['name'];
}
+ } else if (
+ !addressData.region_id
+ && countryData()[addressData.country_id]
+ && countryData()[addressData.country_id]['regions']
+ ) {
+ addressData.region.region_code = '';
+ addressData.region.region = '';
}
delete addressData.region_id;
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js
index 1d6fea79fe8fc..2021df484d180 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js
@@ -177,7 +177,7 @@ define(
address;
if (this.validateAddressData(addressFlat)) {
- addressFlat = $.extend(true, {}, quote.shippingAddress(), addressFlat);
+ addressFlat = uiRegistry.get('checkoutProvider').shippingAddress;
address = addressConverter.formAddressDataToQuoteAddress(addressFlat);
selectShippingAddress(address);
}
diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php
index de2051cbce9b9..1cb70798dfef2 100644
--- a/app/code/Magento/Ups/Model/Carrier.php
+++ b/app/code/Magento/Ups/Model/Carrier.php
@@ -739,9 +739,13 @@ protected function _getXmlQuotes()
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (bool)$this->getConfigFlag('mode_xml'));
$xmlResponse = curl_exec($ch);
-
- $debugData['result'] = $xmlResponse;
- $this->_setCachedQuotes($xmlRequest, $xmlResponse);
+ if ($xmlResponse !== false) {
+ $debugData['result'] = $xmlResponse;
+ $this->_setCachedQuotes($xmlRequest, $xmlResponse);
+ } else {
+ $debugData['result'] = ['error' => curl_error($ch)];
+ }
+ curl_close($ch);
} catch (\Exception $e) {
$debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()];
$xmlResponse = '';
@@ -1002,7 +1006,11 @@ protected function _getXmlTracking($trackings)
curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$xmlResponse = curl_exec($ch);
- $debugData['result'] = $xmlResponse;
+ if ($xmlResponse !== false) {
+ $debugData['result'] = $xmlResponse;
+ } else {
+ $debugData['result'] = ['error' => curl_error($ch)];
+ }
curl_close($ch);
} catch (\Exception $e) {
$debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()];
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/Method.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/Method.php
index af2815969436a..d56d207f8e281 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/Method.php
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/Method.php
@@ -42,6 +42,20 @@ class Method extends Block
*/
protected $blockWaitElement = '._block-content-loading';
+ /**
+ * Shipping method row locator.
+ *
+ * @var string
+ */
+ private $shippingMethodRow = '#checkout-step-shipping_method tbody tr.row';
+
+ /**
+ * Shipping error row locator.
+ *
+ * @var string
+ */
+ private $shippingError = '#checkout-step-shipping_method tbody tr.row-error';
+
/**
* Select shipping method.
*
@@ -50,10 +64,9 @@ class Method extends Block
*/
public function selectShippingMethod(array $method)
{
- // Code under test uses JavaScript setTimeout at this point as well.
- sleep(3);
+ $this->waitForShippingRates();
+
$selector = sprintf($this->shippingMethod, $method['shipping_method'], $method['shipping_service']);
- $this->waitForElementNotVisible($this->blockWaitElement);
$this->_rootElement->find($selector, Locator::SELECTOR_XPATH)->click();
}
@@ -74,4 +87,62 @@ function () use ($browser, $selector) {
}
);
}
+
+ /**
+ * Wait until shipping rates will appear.
+ *
+ * @return void
+ */
+ public function waitForShippingRates()
+ {
+ // Code under test uses JavaScript setTimeout at this point as well.
+ sleep(3);
+ $this->waitForElementNotVisible($this->blockWaitElement);
+ }
+
+ /**
+ * Return available shipping methods with prices.
+ *
+ * @return array
+ */
+ public function getAvailableMethods()
+ {
+ $this->waitForShippingRates();
+ $methods = $this->_rootElement->getElements($this->shippingMethodRow);
+ $result = [];
+ foreach ($methods as $method) {
+ $methodName = trim($method->find('td.col-method:not(:first-child)')->getText());
+ $methodPrice = trim($method->find('td.col-price')->getText());
+ $methodPrice = $this->escapeCurrency($methodPrice);
+
+ $result[$methodName] = $methodPrice;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Is shipping rates estimation error present.
+ *
+ * @return bool
+ */
+ public function isErrorPresent()
+ {
+ $this->waitForShippingRates();
+
+ return $this->_rootElement->find($this->shippingError)->isVisible();
+ }
+
+ /**
+ * Escape currency in price.
+ *
+ * @param string $price
+ * @return string|null
+ */
+ private function escapeCurrency($price)
+ {
+ preg_match("/^\\D*\\s*([\\d,\\.]+)\\s*\\D*$/", $price, $matches);
+
+ return (isset($matches[1])) ? $matches[1] : null;
+ }
}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertShippingMethodsSuccessEstimateAfterAddressEdit.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertShippingMethodsSuccessEstimateAfterAddressEdit.php
new file mode 100644
index 0000000000000..4c89b2fe05135
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertShippingMethodsSuccessEstimateAfterAddressEdit.php
@@ -0,0 +1,97 @@
+shouldOpenCheckout($checkoutOnepage, $browser)) {
+ $checkoutOnepage->open();
+ }
+
+ if (!empty ($editAddressData)) {
+
+ $address = $fixtureFactory->createByCode('address', ['data' => $editAddressData]);
+ $testStepFactory->create(
+ FillShippingAddressStep::class,
+ [
+ 'checkoutOnepage' => $checkoutOnepage,
+ 'shippingAddress' => $address
+ ]
+ )->run();
+
+ \PHPUnit_Framework_Assert::assertFalse(
+ $checkoutOnepage->getShippingMethodBlock()->isErrorPresent(),
+ 'Shipping estimation error is present.'
+ );
+
+ $methods = $checkoutOnepage->getShippingMethodBlock()->getAvailableMethods();
+ \PHPUnit_Framework_Assert::assertNotEmpty(
+ $methods,
+ 'No shipping methods are present.'
+ );
+ }
+ }
+
+ /**
+ * Should open checkout page or not.
+ *
+ * @param CheckoutOnepage $checkoutOnepage
+ * @param BrowserInterface $browser
+ * @return bool
+ */
+ private function shouldOpenCheckout(CheckoutOnepage $checkoutOnepage, BrowserInterface $browser)
+ {
+ $result = true;
+
+ foreach (['checkout/', $checkoutOnepage::MCA] as $path) {
+ $length = strlen($path);
+ if (substr($browser->getUrl(), -$length) === $path) {
+ $result = false;
+ break;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Returns a string representation of the object.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return "Shipping methods are present on checkout page after address modification.";
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageEstimateShippingMethodsTest.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageEstimateShippingMethodsTest.php
new file mode 100644
index 0000000000000..35c3b811f887c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageEstimateShippingMethodsTest.php
@@ -0,0 +1,38 @@
+executeScenario();
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillShippingAddressStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillShippingAddressStep.php
index 0947fd61673d3..d4dfe4a1b6d09 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillShippingAddressStep.php
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillShippingAddressStep.php
@@ -51,6 +51,7 @@ public function run()
{
if ($this->shippingAddress) {
$this->checkoutOnepage->getShippingBlock()->fill($this->shippingAddress);
+ $this->checkoutOnepage->getShippingMethodBlock()->waitForShippingRates();
}
}
}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/ResolveShippingMethodsStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/ResolveShippingMethodsStep.php
new file mode 100644
index 0000000000000..46d160d29fa68
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/ResolveShippingMethodsStep.php
@@ -0,0 +1,55 @@
+checkoutOnepage = $checkoutOnepage;
+ $this->openPage = $openPage;
+ }
+
+ /**
+ * Run step flow.
+ *
+ * @return array
+ */
+ public function run()
+ {
+ if ($this->openPage) {
+ $this->checkoutOnepage->open();
+ }
+
+ $methods = $this->checkoutOnepage->getShippingMethodBlock()->getAvailableMethods();
+ return ['shippingMethods' => $methods];
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml
index 743c30c4c578c..7f6c5bfc1f798 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml
@@ -28,4 +28,12 @@
+
+
+
+
+
+
+
+
diff --git a/dev/tests/functional/tests/app/Magento/Ups/Test/TestCase/OnePageEstimateShippingMethodsTest.xml b/dev/tests/functional/tests/app/Magento/Ups/Test/TestCase/OnePageEstimateShippingMethodsTest.xml
new file mode 100644
index 0000000000000..684b182bb4c2b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Ups/Test/TestCase/OnePageEstimateShippingMethodsTest.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+ catalogProductSimple::default
+ US_address_1_without_email
+
+ - Birmingham
+ - Alabama
+ - 35201
+
+ ups, shipping_origin_US_CA
+
+
+
+