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 + + + +