diff --git a/app/code/Magento/Authorizenet/Model/Authorizenet.php b/app/code/Magento/Authorizenet/Model/Authorizenet.php index 9ab3317a43bb97d950ab32196ce1f9596ba8f7e4..4408c68436707cbfae7332f32cf7d3c902b531f0 100644 --- a/app/code/Magento/Authorizenet/Model/Authorizenet.php +++ b/app/code/Magento/Authorizenet/Model/Authorizenet.php @@ -332,7 +332,7 @@ abstract class Authorizenet extends \Magento\Payment\Model\Method\Cc ->setXCity($billing->getCity()) ->setXState($billing->getRegion()) ->setXZip($billing->getPostcode()) - ->setXCountry($billing->getCountry()) + ->setXCountry($billing->getCountryId()) ->setXPhone($billing->getTelephone()) ->setXFax($billing->getFax()) ->setXCustId($order->getCustomerId()) @@ -352,7 +352,7 @@ abstract class Authorizenet extends \Magento\Payment\Model\Method\Cc ->setXShipToCity($shipping->getCity()) ->setXShipToState($shipping->getRegion()) ->setXShipToZip($shipping->getPostcode()) - ->setXShipToCountry($shipping->getCountry()); + ->setXShipToCountry($shipping->getCountryId()); } $request->setXPoNum($payment->getPoNumber()) diff --git a/app/code/Magento/Authorizenet/Model/Directpost/Request.php b/app/code/Magento/Authorizenet/Model/Directpost/Request.php index 8be7ed5da15ac1dd627ce691ef1cd6eaf9455824..4d5da3e76dc1c3eb4ff204e9ec388f9cece87865 100644 --- a/app/code/Magento/Authorizenet/Model/Directpost/Request.php +++ b/app/code/Magento/Authorizenet/Model/Directpost/Request.php @@ -123,7 +123,7 @@ class Request extends AuthorizenetRequest ->setXCity(strval($billing->getCity())) ->setXState(strval($billing->getRegion())) ->setXZip(strval($billing->getPostcode())) - ->setXCountry(strval($billing->getCountry())) + ->setXCountry(strval($billing->getCountryId())) ->setXPhone(strval($billing->getTelephone())) ->setXFax(strval($billing->getFax())) ->setXCustId(strval($billing->getCustomerId())) @@ -151,7 +151,7 @@ class Request extends AuthorizenetRequest )->setXShipToZip( strval($shipping->getPostcode()) )->setXShipToCountry( - strval($shipping->getCountry()) + strval($shipping->getCountryId()) ); } diff --git a/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js b/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js index ea832acb537e0051e34f976c050c9b8bd7d289b7..14729714b4e608f8c422da8c220b9ea1ed115ffb 100644 --- a/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js +++ b/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js @@ -28,7 +28,7 @@ define([ self.$selector = $('#' + self.selector); self.$container = $('#' + self.container); self.$selector.on( - 'setVaultNotActive', + 'setVaultNotActive.' + self.getCode(), function () { self.$selector.off('submitOrder.' + self.getCode()); } diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php b/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php index 950e2253a95dc21218ee666bb5d747b3991d3118..d2a3196868543db0fb9832aca40529df2c32f965 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php @@ -94,13 +94,16 @@ class GalleryManagement implements \Magento\Catalog\Api\ProductAttributeMediaGal } $found = false; foreach ($existingMediaGalleryEntries as $key => $existingEntry) { + $entryTypes = (array)$entry->getTypes(); + $existingEntryTypes = (array)$existingMediaGalleryEntries[$key]->getTypes(); + $existingMediaGalleryEntries[$key]->setTypes(array_diff($existingEntryTypes, $entryTypes)); + if ($existingEntry->getId() == $entry->getId()) { $found = true; if ($entry->getFile()) { $entry->setId(null); } $existingMediaGalleryEntries[$key] = $entry; - break; } } if (!$found) { diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php b/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php index 3c757f8a05a2daf0ab30c9efb2031c15cefa1d4f..ec2521350d14d991e9c8deff2a74f5ff4865fbfc 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php @@ -298,11 +298,11 @@ class Processor if (is_array($mediaAttribute)) { foreach ($mediaAttribute as $attribute) { if (in_array($attribute, $mediaAttributeCodes)) { - $product->setData($attribute, null); + $product->setData($attribute, 'no_selection'); } } } elseif (in_array($mediaAttribute, $mediaAttributeCodes)) { - $product->setData($mediaAttribute, null); + $product->setData($mediaAttribute, 'no_selection'); } return $this; diff --git a/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php b/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php index a940e09bd57b56a026bba1a45312b94b7f1c80e3..c144daf8c71bd3dc035338af0283df31009e0126 100644 --- a/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php +++ b/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php @@ -29,18 +29,8 @@ class FinalPriceBox extends BasePriceBox } $result = parent::_toHtml(); - - try { - /** @var MsrpPrice $msrpPriceType */ - $msrpPriceType = $this->getSaleableItem()->getPriceInfo()->getPrice('msrp_price'); - } catch (\InvalidArgumentException $e) { - $this->_logger->critical($e); - return $this->wrapResult($result); - } - //Renders MSRP in case it is enabled - $product = $this->getSaleableItem(); - if ($msrpPriceType->canApplyMsrp($product) && $msrpPriceType->isMinimalPriceLessMsrp($product)) { + if ($this->isMsrpPriceApplicable()) { /** @var BasePriceBox $msrpBlock */ $msrpBlock = $this->rendererPool->createPriceRender( MsrpPrice::PRICE_CODE, @@ -56,6 +46,25 @@ class FinalPriceBox extends BasePriceBox return $this->wrapResult($result); } + /** + * Check is MSRP applicable for the current product. + * + * @return bool + */ + protected function isMsrpPriceApplicable() + { + try { + /** @var MsrpPrice $msrpPriceType */ + $msrpPriceType = $this->getSaleableItem()->getPriceInfo()->getPrice('msrp_price'); + } catch (\InvalidArgumentException $e) { + $this->_logger->critical($e); + return false; + } + + $product = $this->getSaleableItem(); + return $msrpPriceType->canApplyMsrp($product) && $msrpPriceType->isMinimalPriceLessMsrp($product); + } + /** * Wrap with standard required container * diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php index fb2d197749e01bdd15b1574d2fca4831a04e4583..e3845a2b51cec716d37e27430023ee2be2409bef 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php @@ -191,20 +191,33 @@ class GalleryManagementTest extends \PHPUnit_Framework_TestCase $productSku = 'testProduct'; $entryMock = $this->getMock(\Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface::class); $entryId = 42; + $entrySecondId = 43; $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) ->willReturn($this->productMock); $existingEntryMock = $this->getMock( \Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface::class ); + $existingSecondEntryMock = $this->getMock( + \Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface::class + ); + $existingEntryMock->expects($this->once())->method('getId')->willReturn($entryId); + $existingEntryMock->expects($this->once())->method('getTypes')->willReturn(['small_image']); + $existingEntryMock->expects($this->once())->method('setTypes')->with(['small_image']); + $existingSecondEntryMock->expects($this->once())->method('getId')->willReturn($entrySecondId); + $existingSecondEntryMock->expects($this->once())->method('getTypes')->willReturn(['image']); + $existingSecondEntryMock->expects($this->once())->method('setTypes')->with([]); $this->productMock->expects($this->once())->method('getMediaGalleryEntries') - ->willReturn([$existingEntryMock]); - $entryMock->expects($this->once())->method('getId')->willReturn($entryId); + ->willReturn([$existingEntryMock, $existingSecondEntryMock]); + + $entryMock->expects($this->exactly(2))->method('getId')->willReturn($entryId); $entryMock->expects($this->once())->method('getFile')->willReturn("base64"); $entryMock->expects($this->once())->method('setId')->with(null); + $entryMock->expects($this->exactly(2))->method('getTypes')->willReturn(['image']); $this->productMock->expects($this->once())->method('setMediaGalleryEntries') - ->willReturn([$entryMock]); + ->with([$entryMock, $existingSecondEntryMock]) + ->willReturnSelf(); $this->productRepositoryMock->expects($this->once())->method('save')->with($this->productMock); $this->assertTrue($this->model->update($productSku, $entryMock)); } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/ProcessorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/ProcessorTest.php index 61d4e3a5c76d5a3fdf57438c082a210c9b60ac5a..50c3c4ad0122c5490fa535c07fa7d677514d91c9 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/ProcessorTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/ProcessorTest.php @@ -197,4 +197,56 @@ class ProcessorTest extends \PHPUnit_Framework_TestCase [false] ]; } + + /** + * @param int $setDataExpectsCalls + * @param string|null $setDataArgument + * @param array|string $mediaAttribute + * @dataProvider clearMediaAttributeDataProvider + */ + public function testClearMediaAttribute($setDataExpectsCalls, $setDataArgument, $mediaAttribute) + { + $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) + ->disableOriginalConstructor() + ->getMock(); + + $productMock->expects($this->exactly($setDataExpectsCalls)) + ->method('setData') + ->with($setDataArgument, 'no_selection'); + + $this->mediaConfig->expects($this->once()) + ->method('getMediaAttributeCodes') + ->willReturn(['image', 'small_image']); + + $this->assertSame($this->model, $this->model->clearMediaAttribute($productMock, $mediaAttribute)); + } + + /** + * @return array + */ + public function clearMediaAttributeDataProvider() + { + return [ + [ + 'setDataExpectsCalls' => 1, + 'setDataArgument' => 'image', + 'mediaAttribute' => 'image', + ], + [ + 'setDataExpectsCalls' => 1, + 'setDataArgument' => 'image', + 'mediaAttribute' => ['image'], + ], + [ + 'setDataExpectsCalls' => 0, + 'setDataArgument' => null, + 'mediaAttribute' => 'some_image', + ], + [ + 'setDataExpectsCalls' => 0, + 'setDataArgument' => null, + 'mediaAttribute' => ['some_image'], + ], + ]; + } } diff --git a/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php b/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php index 283309247cd9d0fbdc9edc8b0cb2bf2d06b2f33c..e40aae5d189b04b9e63911fddbe4813e378fcfa8 100644 --- a/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php +++ b/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php @@ -82,7 +82,7 @@ class Combine extends \Magento\Rule\Model\Condition\Combine public function collectValidatedAttributes($productCollection) { foreach ($this->getConditions() as $condition) { - $condition->addToCollection($productCollection); + $condition->collectValidatedAttributes($productCollection); } return $this; } diff --git a/app/code/Magento/CatalogWidget/Model/Rule/Condition/Product.php b/app/code/Magento/CatalogWidget/Model/Rule/Condition/Product.php index 262ba8f6a6d8dd198da0cb85c87e37a4c1d73795..7d41741135b80498f9b77cc77e4014369efaefc1 100644 --- a/app/code/Magento/CatalogWidget/Model/Rule/Condition/Product.php +++ b/app/code/Magento/CatalogWidget/Model/Rule/Condition/Product.php @@ -223,4 +223,12 @@ class Product extends \Magento\Rule\Model\Condition\Product\AbstractProduct return $result; } + + /** + * {@inheritdoc} + */ + public function collectValidatedAttributes($productCollection) + { + return $this->addToCollection($productCollection); + } } diff --git a/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php b/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php index fa6474e31e7ccb715c09d1b8d2df5523f2ec9f13..dd42ee1c7c9216fc3749a92c643c4afc972bc233 100644 --- a/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php +++ b/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php @@ -80,9 +80,9 @@ class CombineTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); $condition = $this->getMockBuilder(\Magento\CatalogWidget\Model\Rule\Condition\Combine::class) - ->disableOriginalConstructor()->setMethods(['addToCollection']) + ->disableOriginalConstructor()->setMethods(['collectValidatedAttributes']) ->getMock(); - $condition->expects($this->any())->method('addToCollection')->with($collection) + $condition->expects($this->any())->method('collectValidatedAttributes')->with($collection) ->will($this->returnSelf()); $this->condition->setConditions([$condition]); diff --git a/app/code/Magento/Checkout/Block/Cart/LayoutProcessor.php b/app/code/Magento/Checkout/Block/Cart/LayoutProcessor.php index a492002b0a5a5f55219efe09c3422c39f46e9fee..a042c41634bcb615921b93e01c4c42b23bfb8cd4 100644 --- a/app/code/Magento/Checkout/Block/Cart/LayoutProcessor.php +++ b/app/code/Magento/Checkout/Block/Cart/LayoutProcessor.php @@ -85,14 +85,14 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso 'visible' => true, 'formElement' => 'select', 'label' => __('Country'), - 'options' => $this->countryCollection->loadByStore()->toOptionArray(), + 'options' => [], 'value' => null ], 'region_id' => [ 'visible' => true, 'formElement' => 'select', 'label' => __('State/Province'), - 'options' => $this->regionCollection->load()->toOptionArray(), + 'options' => [], 'value' => null ], 'postcode' => [ @@ -103,6 +103,13 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso ] ]; + if (!isset($jsLayout['components']['checkoutProvider']['dictionaries'])) { + $jsLayout['components']['checkoutProvider']['dictionaries'] = [ + 'country_id' => $this->countryCollection->loadByStore()->toOptionArray(), + 'region_id' => $this->regionCollection->addAllowedCountriesFilter()->toOptionArray(), + ]; + } + if (isset($jsLayout['components']['block-summary']['children']['block-shipping']['children'] ['address-fieldsets']['children']) ) { diff --git a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php index 1882d88e04a8b25f51ccf0afbd92a1635f443735..e7686e4bea58b3a5f4db81e1b11f2e17770744c8 100644 --- a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php +++ b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php @@ -192,6 +192,15 @@ class AttributeMerger 'visible' => isset($additionalConfig['visible']) ? $additionalConfig['visible'] : true, ]; + if ($attributeCode === 'region_id' || $attributeCode === 'country_id') { + unset($element['options']); + $element['deps'] = [$providerName]; + $element['imports'] = [ + 'initialOptions' => 'index = ' . $providerName . ':dictionaries.' . $attributeCode, + 'setOptions' => 'index = ' . $providerName . ':dictionaries.' . $attributeCode + ]; + } + if (isset($attributeConfig['value']) && $attributeConfig['value'] != null) { $element['value'] = $attributeConfig['value']; } elseif (isset($attributeConfig['default']) && $attributeConfig['default'] != null) { @@ -341,11 +350,11 @@ class AttributeMerger * @param string $attributeCode * @param array $attributeConfig * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ protected function getFieldOptions($attributeCode, array $attributeConfig) { - $options = isset($attributeConfig['options']) ? $attributeConfig['options'] : []; - return ($attributeCode == 'country_id') ? $this->orderCountryOptions($options) : $options; + return isset($attributeConfig['options']) ? $attributeConfig['options'] : []; } /** @@ -353,6 +362,7 @@ class AttributeMerger * * @param array $countryOptions * @return array + * @deprecated */ protected function orderCountryOptions(array $countryOptions) { diff --git a/app/code/Magento/Checkout/Block/Checkout/DirectoryDataProcessor.php b/app/code/Magento/Checkout/Block/Checkout/DirectoryDataProcessor.php new file mode 100644 index 0000000000000000000000000000000000000000..4a02ebbd079a407e531f17168531a5f9439915fb --- /dev/null +++ b/app/code/Magento/Checkout/Block/Checkout/DirectoryDataProcessor.php @@ -0,0 +1,146 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Block\Checkout; + +use Magento\Directory\Helper\Data as DirectoryHelper; +use Magento\Store\Api\StoreResolverInterface; + +/** + * Directory data processor. + * + * This class adds various country and region dictionaries to checkout page. + * This data can be used by other UI components during checkout flow. + */ +class DirectoryDataProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcessorInterface +{ + /** + * @var array + */ + private $countryOptions; + + /** + * @var array + */ + private $regionOptions; + + /** + * @var \Magento\Directory\Model\ResourceModel\Region\CollectionFactory + */ + private $regionCollectionFactory; + + /** + * @var \Magento\Directory\Model\ResourceModel\Region\CollectionFactory + */ + private $countryCollectionFactory; + + /** + * @var StoreResolverInterface + */ + private $storeResolver; + + /** + * @var DirectoryHelper + */ + private $directoryHelper; + + /** + * @param \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollection + * @param \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionCollection + * @param StoreResolverInterface $storeResolver + * @param DirectoryHelper $directoryHelper + */ + public function __construct( + \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollection, + \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionCollection, + StoreResolverInterface $storeResolver, + DirectoryHelper $directoryHelper + ) { + $this->countryCollectionFactory = $countryCollection; + $this->regionCollectionFactory = $regionCollection; + $this->storeResolver = $storeResolver; + $this->directoryHelper = $directoryHelper; + } + + /** + * Process js Layout of block + * + * @param array $jsLayout + * @return array + */ + public function process($jsLayout) + { + if (!isset($jsLayout['components']['checkoutProvider']['dictionaries'])) { + $jsLayout['components']['checkoutProvider']['dictionaries'] = [ + 'country_id' => $this->getCountryOptions(), + 'region_id' => $this->getRegionOptions(), + ]; + } + + return $jsLayout; + } + + /** + * Get country options list. + * + * @return array + */ + private function getCountryOptions() + { + if (!isset($this->countryOptions)) { + $this->countryOptions = $this->countryCollectionFactory->create()->loadByStore( + $this->storeResolver->getCurrentStoreId() + )->toOptionArray(); + $this->countryOptions = $this->orderCountryOptions($this->countryOptions); + } + + return $this->countryOptions; + } + + /** + * Get region options list. + * + * @return array + */ + private function getRegionOptions() + { + if (!isset($this->regionOptions)) { + $this->regionOptions = $this->regionCollectionFactory->create()->addAllowedCountriesFilter( + $this->storeResolver->getCurrentStoreId() + )->toOptionArray(); + } + + return $this->regionOptions; + } + + /** + * Sort country options by top country codes. + * + * @param array $countryOptions + * @return array + */ + private function orderCountryOptions(array $countryOptions) + { + $topCountryCodes = $this->directoryHelper->getTopCountryCodes(); + if (empty($topCountryCodes)) { + return $countryOptions; + } + + $headOptions = []; + $tailOptions = [[ + 'value' => 'delimiter', + 'label' => '──────────', + 'disabled' => true, + ]]; + foreach ($countryOptions as $countryOption) { + if (empty($countryOption['value']) || in_array($countryOption['value'], $topCountryCodes)) { + array_push($headOptions, $countryOption); + } else { + array_push($tailOptions, $countryOption); + } + } + return array_merge($headOptions, $tailOptions); + } +} diff --git a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php index 1b2c7444198915c866a55ca2cc9b8e6b29544e39..fd8434703ab756a2664e235332d09e13e7890e19 100644 --- a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php +++ b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php @@ -7,7 +7,11 @@ namespace Magento\Checkout\Block\Checkout; use Magento\Checkout\Helper\Data; use Magento\Framework\App\ObjectManager; +use Magento\Store\Api\StoreResolverInterface; +/** + * Class LayoutProcessor + */ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcessorInterface { /** @@ -35,6 +39,16 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso */ private $checkoutDataHelper; + /** + * @var StoreResolverInterface + */ + private $storeResolver; + + /** + * @var \Magento\Shipping\Model\Config + */ + private $shippingConfig; + /** * @param \Magento\Customer\Model\AttributeMetadataDataProvider $attributeMetadataDataProvider * @param \Magento\Ui\Component\Form\AttributeMapper $attributeMapper @@ -146,6 +160,16 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso $elements ); } + if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children'] + ['step-config']['children']['shipping-rates-validation']['children'] + )) { + $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children'] + ['step-config']['children']['shipping-rates-validation']['children'] = + $this->processShippingChildrenComponents( + $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children'] + ['step-config']['children']['shipping-rates-validation']['children'] + ); + } if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step'] ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'] @@ -163,6 +187,26 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso return $jsLayout; } + /** + * Process shipping configuration to exclude inactive carriers. + * + * @param array $shippingRatesLayout + * @return array + */ + private function processShippingChildrenComponents($shippingRatesLayout) + { + $activeCarriers = $this->getShippingConfig()->getActiveCarriers( + $this->getStoreResolver()->getCurrentStoreId() + ); + foreach (array_keys($shippingRatesLayout) as $carrierName) { + $carrierKey = str_replace('-rates-validation', '', $carrierName); + if (!array_key_exists($carrierKey, $activeCarriers)) { + unset($shippingRatesLayout[$carrierName]); + } + } + return $shippingRatesLayout; + } + /** * Appends billing address form component to payment layout * @param array $paymentLayout @@ -314,4 +358,34 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso return $this->checkoutDataHelper; } + + /** + * Retrieve Shipping Configuration. + * + * @return \Magento\Shipping\Model\Config + * @deprecated + */ + private function getShippingConfig() + { + if (!$this->shippingConfig) { + $this->shippingConfig = ObjectManager::getInstance()->get(\Magento\Shipping\Model\Config::class); + } + + return $this->shippingConfig; + } + + /** + * Get store resolver. + * + * @return StoreResolverInterface + * @deprecated + */ + private function getStoreResolver() + { + if (!$this->storeResolver) { + $this->storeResolver = ObjectManager::getInstance()->get(StoreResolverInterface::class); + } + + return $this->storeResolver; + } } diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Cart/LayoutProcessorTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Cart/LayoutProcessorTest.php index 95ffed86cbb35177051303726222813942336c72..5eabb6c9c86a47def05a69762c21f0b47f5a608f 100644 --- a/app/code/Magento/Checkout/Test/Unit/Block/Cart/LayoutProcessorTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Block/Cart/LayoutProcessorTest.php @@ -69,7 +69,7 @@ class LayoutProcessorTest extends \PHPUnit_Framework_TestCase $this->countryCollection->expects($this->once())->method('loadByStore')->willReturnSelf(); $this->countryCollection->expects($this->once())->method('toOptionArray')->willReturn($countries); - $this->regionCollection->expects($this->once())->method('load')->willReturnSelf(); + $this->regionCollection->expects($this->once())->method('addAllowedCountriesFilter')->willReturnSelf(); $this->regionCollection->expects($this->once())->method('toOptionArray')->willReturn($regions); $layoutMerged = $layout; @@ -77,7 +77,12 @@ class LayoutProcessorTest extends \PHPUnit_Framework_TestCase ['address-fieldsets']['children']['fieldThree'] = ['param' => 'value']; $layoutMergedPointer = &$layoutMerged['components']['block-summary']['children']['block-shipping'] ['children']['address-fieldsets']['children']; - + $layoutMerged['components']['checkoutProvider'] = [ + 'dictionaries' => [ + 'country_id' => [], + 'region_id' => [], + ] + ]; $elements = [ 'city' => [ 'visible' => false, diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Checkout/DirectoryDataProcessorTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/DirectoryDataProcessorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c84fac464c047ad611268d26ac988adb2b419596 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/DirectoryDataProcessorTest.php @@ -0,0 +1,114 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Test\Unit\Block\Checkout; + +class DirectoryDataProcessorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Checkout\Block\Checkout\DirectoryDataProcessor + */ + protected $model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $countryCollectionFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $countryCollectionMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $regionCollectionFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $regionCollectionMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeResolverMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $directoryDataHelperMock; + + protected function setUp() + { + $this->countryCollectionFactoryMock = $this->getMock( + \Magento\Directory\Model\ResourceModel\Country\CollectionFactory::class, + ['create'], + [], + '', + false + ); + $this->countryCollectionMock = $this->getMock( + \Magento\Directory\Model\ResourceModel\Country\Collection::class, + [], + [], + '', + false + ); + $this->regionCollectionFactoryMock = $this->getMock( + \Magento\Directory\Model\ResourceModel\Region\CollectionFactory::class, + ['create'], + [], + '', + false + ); + $this->regionCollectionMock = $this->getMock( + \Magento\Directory\Model\ResourceModel\Region\Collection::class, + [], + [], + '', + false + ); + $this->storeResolverMock = $this->getMock( + \Magento\Store\Api\StoreResolverInterface::class + ); + $this->directoryDataHelperMock = $this->getMock( + \Magento\Directory\Helper\Data::class, + [], + [], + '', + false + ); + + $this->model = new \Magento\Checkout\Block\Checkout\DirectoryDataProcessor( + $this->countryCollectionFactoryMock, + $this->regionCollectionFactoryMock, + $this->storeResolverMock, + $this->directoryDataHelperMock + ); + } + + public function testProcess() + { + $expectedResult['components']['checkoutProvider']['dictionaries'] = [ + 'country_id' => [], + 'region_id' => [], + ]; + + $this->countryCollectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->countryCollectionMock); + $this->countryCollectionMock->expects($this->once())->method('loadByStore')->willReturnSelf(); + $this->countryCollectionMock->expects($this->once())->method('toOptionArray')->willReturn([]); + $this->regionCollectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->regionCollectionMock); + $this->regionCollectionMock->expects($this->once())->method('addAllowedCountriesFilter')->willReturnSelf(); + $this->regionCollectionMock->expects($this->once())->method('toOptionArray')->willReturn([]); + + $this->assertEquals($expectedResult, $this->model->process([])); + } +} diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php index 1351213f990b54a573a5d5d3a015e7b940a5f7ee..95aed9b56afc33d2f08f778a2e4b1e2162d35fe6 100644 --- a/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php @@ -17,6 +17,8 @@ use PHPUnit_Framework_MockObject_MockObject as MockObject; /** * LayoutProcessorTest covers a list of variations for * checkout layout processor + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class LayoutProcessorTest extends \PHPUnit_Framework_TestCase { @@ -45,6 +47,11 @@ class LayoutProcessorTest extends \PHPUnit_Framework_TestCase */ private $layoutProcessor; + /** + * @var MockObject + */ + private $storeResolver; + protected function setUp() { $objectManager = new ObjectManager($this); @@ -79,8 +86,11 @@ class LayoutProcessorTest extends \PHPUnit_Framework_TestCase $this->attributeMerger ); + $this->storeResolver = $this->getMock(\Magento\Store\Api\StoreResolverInterface::class); + $objectManager->setBackwardCompatibleProperty($this->layoutProcessor, 'checkoutDataHelper', $this->dataHelper); $objectManager->setBackwardCompatibleProperty($this->layoutProcessor, 'options', $options); + $objectManager->setBackwardCompatibleProperty($this->layoutProcessor, 'storeResolver', $this->storeResolver); } /** diff --git a/app/code/Magento/Checkout/etc/frontend/di.xml b/app/code/Magento/Checkout/etc/frontend/di.xml index 6fb9058c3b7681c8905a40a5eace5d88d8566b6f..69ed33721740d680ec6662e43858e9c42a1c6629 100644 --- a/app/code/Magento/Checkout/etc/frontend/di.xml +++ b/app/code/Magento/Checkout/etc/frontend/di.xml @@ -55,6 +55,7 @@ <argument name="layoutProcessors" xsi:type="array"> <item name="addressFormAttributes" xsi:type="object">Magento\Checkout\Block\Checkout\LayoutProcessor</item> <item name="totalsSortOrder" xsi:type="object">Magento\Checkout\Block\Checkout\TotalsProcessor</item> + <item name="directoryData" xsi:type="object">Magento\Checkout\Block\Checkout\DirectoryDataProcessor</item> </argument> </arguments> </type> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js index 9a3685b212b435e8c03adb7be2cd7a182e591b87..c215b1989edbeafe273819b09f2588f06169b4e5 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js @@ -10,13 +10,13 @@ define([], function () { * Returns new address object */ return function (addressData) { - var identifier = Date.now(); - var regionId = null; + var identifier = Date.now(), + regionId; if (addressData.region && addressData.region.region_id) { regionId = addressData.region.region_id; } else if (addressData.country_id && addressData.country_id == window.checkoutConfig.defaultCountryId) { - regionId = window.checkoutConfig.defaultRegionId; + regionId = window.checkoutConfig.defaultRegionId || undefined; } return { @@ -25,7 +25,7 @@ define([], function () { regionId: regionId || addressData.regionId, regionCode: (addressData.region) ? addressData.region.region_code : null, region: (addressData.region) ? addressData.region.region : null, - customerId: addressData.customer_id, + customerId: addressData.customer_id || addressData.customerId, street: addressData.street, company: addressData.company, telephone: addressData.telephone, diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js index 08641f015f609a9b8c75e80e0cfd39a82a6f5b1e..cd43dc646584d52708f3923c042889fdb20e0d82 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js @@ -50,9 +50,13 @@ define( if (address) { estimatedAddress = address.isEditable() ? addressConverter.quoteAddressToFormAddressData(address) : - addressConverter.quoteAddressToFormAddressData( - addressConverter.addressToEstimationAddress(address) - ); + { + // only the following fields must be used by estimation form data provider + 'country_id': address.countryId, + region: address.region, + 'region_id': address.regionId, + postcode: address.postcode + }; checkoutProvider.set( 'shippingAddress', $.extend({}, checkoutProvider.get('shippingAddress'), estimatedAddress) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js index 8910e41731d11a9be99bf1777dc13e3550781976..fb15e47eaf7d487da1c8671c545f0b99ce2a7445 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js @@ -79,7 +79,6 @@ define( fieldsetName = 'checkout.steps.shipping-step.shippingAddress.shipping-address-fieldset'; this._super(); - shippingRatesValidator.initFields(fieldsetName); if (!quote.isVirtual()) { stepNavigator.registerStep( @@ -120,6 +119,7 @@ define( checkoutProvider.on('shippingAddress', function (shippingAddressData) { checkoutData.setShippingAddressFromData(shippingAddressData); }); + shippingRatesValidator.initFields(fieldsetName); }); return this; diff --git a/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php index 51c68145b24cf5e72061a51647d4b311f39e60bf..a5f85df1c96f66bb911bf92303c40d14c3be49b6 100644 --- a/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php @@ -193,6 +193,7 @@ class Configurable extends \Magento\Catalog\Block\Product\View\AbstractView $config = [ 'attributes' => $attributesData['attributes'], 'template' => str_replace('%s', '<%- data.price %>', $store->getCurrentCurrency()->getOutputFormat()), + 'currencyFormat' => $store->getCurrentCurrency()->getOutputFormat(), 'optionPrices' => $this->getOptionPrices(), 'prices' => [ 'oldPrice' => [ @@ -229,7 +230,17 @@ class Configurable extends \Magento\Catalog\Block\Product\View\AbstractView { $prices = []; foreach ($this->getAllowProducts() as $product) { + $tierPrices = []; $priceInfo = $product->getPriceInfo(); + $tierPriceModel = $priceInfo->getPrice('tier_price'); + $tierPricesList = $tierPriceModel->getTierPriceList(); + foreach ($tierPricesList as $tierPrice) { + $tierPrices[] = [ + 'qty' => $this->_registerJsPrice($tierPrice['price_qty']), + 'price' => $this->_registerJsPrice($tierPrice['price']->getValue()), + 'percentage' => $this->_registerJsPrice($tierPriceModel->getSavePercent($tierPrice['price'])), + ]; + } $prices[$product->getId()] = [ @@ -247,8 +258,9 @@ class Configurable extends \Magento\Catalog\Block\Product\View\AbstractView 'amount' => $this->_registerJsPrice( $priceInfo->getPrice('final_price')->getAmount()->getValue() ), - ] - ]; + ], + 'tierPrices' => $tierPrices, + ]; } return $prices; } @@ -263,4 +275,14 @@ class Configurable extends \Magento\Catalog\Block\Product\View\AbstractView { return str_replace(',', '.', $price); } + + /** + * Should we generate "As low as" block or not + * + * @return bool + */ + public function showMinimalPrice() + { + return true; + } } diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php b/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php new file mode 100644 index 0000000000000000000000000000000000000000..af2414204fd1a3aea6acecceb34f28c613f3c6dc --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\ConfigurableProduct\Pricing\Render; + +/** + * Responsible for displaying tier price box on configurable product page. + * + * @package Magento\ConfigurableProduct\Pricing\Render + */ +class TierPriceBox extends FinalPriceBox +{ + /** + * @inheritdoc + */ + public function toHtml() + { + // Hide tier price block in case of MSRP. + if (!$this->isMsrpPriceApplicable()) { + return parent::toHtml(); + } + } +} diff --git a/app/code/Magento/ConfigurableProduct/view/base/layout/catalog_product_prices.xml b/app/code/Magento/ConfigurableProduct/view/base/layout/catalog_product_prices.xml index 47fe31681b5bf0d96ba4cf4935283d415de23ce7..545b04dc0a3279c92100166bda0ff3922b820bb9 100644 --- a/app/code/Magento/ConfigurableProduct/view/base/layout/catalog_product_prices.xml +++ b/app/code/Magento/ConfigurableProduct/view/base/layout/catalog_product_prices.xml @@ -10,6 +10,10 @@ <arguments> <argument name="configurable" xsi:type="array"> <item name="prices" xsi:type="array"> + <item name="tier_price" xsi:type="array"> + <item name="render_class" xsi:type="string">Magento\ConfigurableProduct\Pricing\Render\TierPriceBox</item> + <item name="render_template" xsi:type="string">Magento_ConfigurableProduct::product/price/tier_price.phtml</item> + </item> <item name="final_price" xsi:type="array"> <item name="render_class" xsi:type="string">Magento\ConfigurableProduct\Pricing\Render\FinalPriceBox</item> <item name="render_template" xsi:type="string">Magento_ConfigurableProduct::product/price/final_price.phtml</item> diff --git a/app/code/Magento/ConfigurableProduct/view/base/templates/product/price/tier_price.phtml b/app/code/Magento/ConfigurableProduct/view/base/templates/product/price/tier_price.phtml new file mode 100644 index 0000000000000000000000000000000000000000..01e6bb4222fd3cf6b178a350b0a3c0667c0263ca --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/view/base/templates/product/price/tier_price.phtml @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +?> +<script type="text/x-magento-template" id="tier-prices-template"> + <ul class="prices-tier items"> + <% _.each(tierPrices, function(item, key) { %> + <% var priceStr = '<span class="price-container price-tier_price">' + + '<span data-price-amount="' + priceUtils.formatPrice(item.price, currencyFormat) + '"' + + ' data-price-type=""' + ' class="price-wrapper ">' + + '<span class="price">' + priceUtils.formatPrice(item.price, currencyFormat) + '</span>' + + '</span>' + + '</span>'; %> + <li class="item"> + <%= $t('Buy %1 for %2 each and').replace('%1', item.qty).replace('%2', priceStr) %> + <strong class="benefit"> + <%= $t('save') %><span class="percent tier-<%= key %>"> <%= item.percentage %></span>% + </strong> + </li> + <% }); %> + </ul> +</script> +<div data-role="tier-price-block"></div> diff --git a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js index 59b313bcb497ddb64e1fdca9bc480afdbbb2f1d9..0c7157f920d9c5f97ec6429fea11bc2aa0af9403 100644 --- a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js +++ b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js @@ -7,11 +7,12 @@ define([ 'jquery', 'underscore', 'mage/template', + 'mage/translate', 'priceUtils', 'priceBox', 'jquery/ui', 'jquery/jquery.parsequery' -], function ($, _, mageTemplate) { +], function ($, _, mageTemplate, $t, priceUtils) { 'use strict'; $.widget('mage.configurable', { @@ -38,7 +39,10 @@ define([ * * @type {String} */ - gallerySwitchStrategy: 'replace' + gallerySwitchStrategy: 'replace', + tierPriceTemplateSelector: '#tier-prices-template', + tierPriceBlockSelector: '[data-role="tier-price-block"]', + tierPriceTemplate: '' }, /** @@ -84,6 +88,7 @@ define([ options.priceFormat = priceBoxOptions.priceFormat; } options.optionTemplate = mageTemplate(options.optionTemplate); + options.tierPriceTemplate = $(this.options.tierPriceTemplateSelector).html(); options.settings = options.spConfig.containerId ? $(options.spConfig.containerId).find(options.superSelector) : @@ -259,6 +264,7 @@ define([ } this._reloadPrice(); this._displayRegularPriceBlock(this.simpleProduct); + this._displayTierPriceBlock(this.simpleProduct); this._changeProductImage(); }, @@ -513,6 +519,31 @@ define([ var galleryObject = element.data('gallery'); this.options.mediaGalleryInitial = galleryObject.returnCurrentImages(); + }, + + /** + * Show or hide tier price block + * + * @param {*} optionId + * @private + */ + _displayTierPriceBlock: function (optionId) { + if (typeof optionId != 'undefined' && + this.options.spConfig.optionPrices[optionId].tierPrices != [] + ) { + var options = this.options.spConfig.optionPrices[optionId]; + if (this.options.tierPriceTemplate) { + var tierPriceHtml = mageTemplate(this.options.tierPriceTemplate, { + 'tierPrices': options.tierPrices, + '$t': $t, + 'currencyFormat': this.options.spConfig.currencyFormat, + 'priceUtils': priceUtils + }); + $(this.options.tierPriceBlockSelector).html(tierPriceHtml).show(); + } + } else { + $(this.options.tierPriceBlockSelector).hide(); + } } }); diff --git a/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js b/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js index 30fbef98fd39ab15db1c7971e3e86ad82e367253..e013a96e4890aee11d30641a2f2ee31c4e6088c2 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js +++ b/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js @@ -10,11 +10,17 @@ define([], function() { * Returns new address object */ return function (addressData) { + var regionId; + + if (addressData.region['region_id'] && addressData.region['region_id'] !== '0') { + regionId = addressData.region['region_id'] + ''; + } + return { customerAddressId: addressData.id, email: addressData.email, countryId: addressData.country_id, - regionId: addressData.region_id, + regionId: regionId, regionCode: addressData.region.region_code, region: addressData.region.region, customerId: addressData.customer_id, diff --git a/app/code/Magento/Directory/Model/ResourceModel/Region/Collection.php b/app/code/Magento/Directory/Model/ResourceModel/Region/Collection.php index 718e0c0223d767dd3857f5c796d9b7f9d918900a..3fdb20165d4bea912e42c94e14c5c0b3e01cdf8e 100644 --- a/app/code/Magento/Directory/Model/ResourceModel/Region/Collection.php +++ b/app/code/Magento/Directory/Model/ResourceModel/Region/Collection.php @@ -9,6 +9,14 @@ */ namespace Magento\Directory\Model\ResourceModel\Region; +use Magento\Directory\Model\AllowedCountries; +use Magento\Framework\App\ObjectManager; +use Magento\Store\Model\ScopeInterface; + +/** + * Class Collection + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection { /** @@ -30,6 +38,11 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab */ protected $_localeResolver; + /** + * @var AllowedCountries + */ + private $allowedCountriesReader; + /** * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory * @param \Psr\Log\LoggerInterface $logger @@ -89,6 +102,40 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab return $this; } + /** + * Return Allowed Countries reader + * + * @return \Magento\Directory\Model\AllowedCountries + * @deprecated + */ + private function getAllowedCountriesReader() + { + if (!$this->allowedCountriesReader) { + $this->allowedCountriesReader = ObjectManager::getInstance()->get(AllowedCountries::class); + } + + return $this->allowedCountriesReader; + } + + /** + * Set allowed countries filter based on the given store. + * This is a convenience method for collection filtering based on store configuration settings. + * + * @param null|int|string|\Magento\Store\Model\Store $store + * @return \Magento\Directory\Model\ResourceModel\Region\Collection + */ + public function addAllowedCountriesFilter($store = null) + { + $allowedCountries = $this->getAllowedCountriesReader() + ->getAllowedCountries(ScopeInterface::SCOPE_STORE, $store); + + if (!empty($allowedCountries)) { + $this->addFieldToFilter('main_table.country_id', ['in' => $allowedCountries]); + } + + return $this; + } + /** * Filter by country_id * diff --git a/app/code/Magento/Directory/Test/Unit/Model/ResourceModel/Region/CollectionTest.php b/app/code/Magento/Directory/Test/Unit/Model/ResourceModel/Region/CollectionTest.php index 59c054b00a5f9c11607ca2126c0e0174918785e6..5c09ab119295a4e511f99f80f8320950a2a8ff57 100644 --- a/app/code/Magento/Directory/Test/Unit/Model/ResourceModel/Region/CollectionTest.php +++ b/app/code/Magento/Directory/Test/Unit/Model/ResourceModel/Region/CollectionTest.php @@ -6,6 +6,7 @@ namespace Magento\Directory\Test\Unit\Model\ResourceModel\Region; use Magento\Directory\Model\ResourceModel\Region\Collection; +use Magento\Directory\Model\AllowedCountries; use Magento\Framework\DB\Adapter\Pdo\Mysql; use Magento\Framework\DB\Select; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; @@ -15,7 +16,14 @@ use Magento\Framework\Data\Collection\EntityFactory; use Magento\Framework\Locale\ResolverInterface; use Magento\Framework\DataObject; use Psr\Log\LoggerInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit_Framework_MockObject_MockObject as MockObject; +/** + * Class CollectionTest + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class CollectionTest extends \PHPUnit_Framework_TestCase { /** @@ -23,15 +31,22 @@ class CollectionTest extends \PHPUnit_Framework_TestCase */ private $collection; + /** + * @var MockObject + */ + private $allowedCountries; + protected function setUp() { + $objectManager = new ObjectManager($this); $entityFactoryMock = $this->getMock(EntityFactory::class, [], [], '', false); $loggerMock = $this->getMock(LoggerInterface::class); $fetchStrategyMock = $this->getMock(FetchStrategyInterface::class); $eventManagerMock = $this->getMock(ManagerInterface::class); $localeResolverMock = $this->getMock(ResolverInterface::class); $connectionMock = $this->getMock(Mysql::class, [], [], '', false); - $resourceMock = $this->getMockForAbstractClass(AbstractDb::class, + $resourceMock = $this->getMockForAbstractClass( + AbstractDb::class, [], '', false, @@ -39,6 +54,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase true, ['getConnection', 'getMainTable', 'getTable', '__wakeup'] ); + $this->allowedCountries = $this->getMock(AllowedCountries::class, [], [], '', false); $selectMock = $this->getMock(Select::class, [], [], '', false); $connectionMock->expects($this->any())->method('select')->will($this->returnValue($selectMock)); @@ -54,6 +70,12 @@ class CollectionTest extends \PHPUnit_Framework_TestCase $connectionMock, $resourceMock ); + + $objectManager->setBackwardCompatibleProperty( + $this->collection, + 'allowedCountriesReader', + $this->allowedCountries + ); } public function testToOptionArray() @@ -98,4 +120,14 @@ class CollectionTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expectedResult, $this->collection->toOptionArray()); } + + public function testAddAllowedCountriesFilter() + { + $allowedCountries = [1, 2, 3]; + $this->allowedCountries->expects($this->once())->method('getAllowedCountries')->with( + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + null + )->willReturn($allowedCountries); + $this->assertEquals($this->collection->addAllowedCountriesFilter(), $this->collection); + } } diff --git a/app/code/Magento/Multishipping/Block/Checkout/Billing/Items.php b/app/code/Magento/Multishipping/Block/Checkout/Billing/Items.php index 5a3e581d5375bb983baac8516b63788331388da9..3d2ca91d3ba6c0b687a6361858ce13269967861e 100644 --- a/app/code/Magento/Multishipping/Block/Checkout/Billing/Items.php +++ b/app/code/Magento/Multishipping/Block/Checkout/Billing/Items.php @@ -68,7 +68,7 @@ class Items extends \Magento\Sales\Block\Items\AbstractItems */ public function getVirtualProductEditUrl() { - return $this->getUrl('*/cart'); + return $this->getUrl('checkout/cart'); } /** diff --git a/app/code/Magento/Multishipping/Block/Checkout/Overview.php b/app/code/Magento/Multishipping/Block/Checkout/Overview.php index 0031b6416d333eb32eb032ead7267ca4d8f9da9c..299e85d6f13c31a4633d9886f4565866def62802 100644 --- a/app/code/Magento/Multishipping/Block/Checkout/Overview.php +++ b/app/code/Magento/Multishipping/Block/Checkout/Overview.php @@ -297,7 +297,7 @@ class Overview extends \Magento\Sales\Block\Items\AbstractItems */ public function getVirtualProductEditUrl() { - return $this->getUrl('*/cart'); + return $this->getUrl('checkout/cart'); } /** diff --git a/app/code/Magento/Multishipping/Test/Unit/Block/Checkout/Billing/ItemsTest.php b/app/code/Magento/Multishipping/Test/Unit/Block/Checkout/Billing/ItemsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..056ac173621743ac162ba744d83a60d097cf12fc --- /dev/null +++ b/app/code/Magento/Multishipping/Test/Unit/Block/Checkout/Billing/ItemsTest.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Multishipping\Test\Unit\Block\Checkout\Billing; + + +class ItemsTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Multishipping\Block\Checkout\Billing\Items + */ + private $model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $urlBuilderMock; + + protected function setUp() + { + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->urlBuilderMock = $this->getMock(\Magento\Framework\UrlInterface::class); + $this->model = $objectManager->getObject( + \Magento\Multishipping\Block\Checkout\Billing\Items::class, + [ + 'urlBuilder' => $this->urlBuilderMock + ] + ); + } + + public function testGetVirtualProductEditUrl() + { + $url = 'http://example.com'; + $this->urlBuilderMock->expects($this->once())->method('getUrl')->with('checkout/cart', [])->willReturn($url); + $this->assertEquals($url, $this->model->getVirtualProductEditUrl()); + } +} diff --git a/app/code/Magento/Multishipping/Test/Unit/Block/Checkout/OverviewTest.php b/app/code/Magento/Multishipping/Test/Unit/Block/Checkout/OverviewTest.php index fc2169f38e4af88559b112931ac0952ecd82f5d0..b583ad258595b7101fb8683df6c9932a20ee1b3f 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Block/Checkout/OverviewTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Block/Checkout/OverviewTest.php @@ -52,6 +52,11 @@ class OverviewTest extends \PHPUnit_Framework_TestCase */ protected $quoteMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $urlBuilderMock; + protected function setUp() { $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -83,13 +88,15 @@ class OverviewTest extends \PHPUnit_Framework_TestCase $this->checkoutMock = $this->getMock(\Magento\Multishipping\Model\Checkout\Type\Multishipping::class, [], [], '', false); $this->quoteMock = $this->getMock(\Magento\Quote\Model\Quote::class, [], [], '', false); + $this->urlBuilderMock = $this->getMock(\Magento\Framework\UrlInterface::class); $this->model = $objectManager->getObject( \Magento\Multishipping\Block\Checkout\Overview::class, [ 'priceCurrency' => $this->priceCurrencyMock, 'totalsCollector' => $this->totalsCollectorMock, 'totalsReader' => $this->totalsReaderMock, - 'multishipping' => $this->checkoutMock + 'multishipping' => $this->checkoutMock, + 'urlBuilder' => $this->urlBuilderMock ] ); } @@ -189,4 +196,11 @@ class OverviewTest extends \PHPUnit_Framework_TestCase ->willReturn([$totalMock]); return $totalMock; } + + public function testGetVirtualProductEditUrl() + { + $url = 'http://example.com'; + $this->urlBuilderMock->expects($this->once())->method('getUrl')->with('checkout/cart', [])->willReturn($url); + $this->assertEquals($url, $this->model->getVirtualProductEditUrl()); + } } diff --git a/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php b/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php new file mode 100644 index 0000000000000000000000000000000000000000..5b107b74295b3a842c00429543b00e0466b1d530 --- /dev/null +++ b/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php @@ -0,0 +1,73 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Plugin; + +/** + * Class PaymentConfigurationProcess + * + * Removes inactive payment methods and group from checkout configuration. + */ +class PaymentConfigurationProcess +{ + /** + * @var \Magento\Payment\Api\PaymentMethodListInterface + */ + private $paymentMethodList; + + /** + * @var \Magento\Store\Model\StoreManagerInterface + */ + private $storeManager; + + /** + * @param \Magento\Payment\Api\PaymentMethodListInterface $paymentMethodList + * @param \Magento\Store\Model\StoreManagerInterface $storeManager + */ + public function __construct( + \Magento\Payment\Api\PaymentMethodListInterface $paymentMethodList, + \Magento\Store\Model\StoreManagerInterface $storeManager + ) { + $this->paymentMethodList = $paymentMethodList; + $this->storeManager = $storeManager; + } + + /** + * Checkout LayoutProcessor before process plugin. + * + * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $processor + * @param array $jsLayout + * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforeProcess(\Magento\Checkout\Block\Checkout\LayoutProcessor $processor, $jsLayout) + { + $configuration = &$jsLayout['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children']; + + if (!isset($configuration)) { + return [$jsLayout]; + } + + $storeId = $this->storeManager->getStore()->getId(); + $activePaymentMethodList = $this->paymentMethodList->getActiveList($storeId); + $getCodeFunc = function ($method) { + return $method->getCode(); + }; + $activePaymentMethodCodes = array_map($getCodeFunc, $activePaymentMethodList); + + foreach ($configuration as $paymentGroup => $groupConfig) { + $notActivePaymentMethodCodes = array_diff(array_keys($groupConfig['methods']), $activePaymentMethodCodes); + foreach ($notActivePaymentMethodCodes as $notActivePaymentMethodCode) { + unset($configuration[$paymentGroup]['methods'][$notActivePaymentMethodCode]); + } + if (empty($configuration[$paymentGroup]['methods'])) { + unset($configuration[$paymentGroup]); + } + } + + return [$jsLayout]; + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Plugin/PaymentConfigurationProcessTest.php b/app/code/Magento/Payment/Test/Unit/Plugin/PaymentConfigurationProcessTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3e49c8718e6044de36cc6a1018d052dc48ed7485 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Plugin/PaymentConfigurationProcessTest.php @@ -0,0 +1,146 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Plugin; + +/** + * Class PaymentConfigurationProcessTest. + */ +class PaymentConfigurationProcessTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeManager; + + /** + * @var \Magento\Store\Api\Data\StoreInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $store; + + /** + * @var \Magento\Payment\Api\PaymentMethodListInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $paymentMethodList; + + /** + * @var \Magento\Checkout\Block\Checkout\LayoutProcessor|\PHPUnit_Framework_MockObject_MockObject + */ + private $layoutProcessor; + + /** + * @var \Magento\Payment\Plugin\PaymentConfigurationProcess + */ + private $plugin; + + /** + * Set up + */ + protected function setUp() + { + $this->storeManager = $this + ->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getStore']) + ->getMockForAbstractClass(); + $this->store = $this + ->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getId']) + ->getMockForAbstractClass(); + $this->paymentMethodList = $this + ->getMockBuilder(\Magento\Payment\Api\PaymentMethodListInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getActiveList']) + ->getMockForAbstractClass(); + $this->layoutProcessor = $this + ->getMockBuilder(\Magento\Checkout\Block\Checkout\LayoutProcessor::class) + ->disableOriginalConstructor() + ->setMethods(['process']) + ->getMockForAbstractClass(); + + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->plugin = $objectManagerHelper->getObject( + \Magento\Payment\Plugin\PaymentConfigurationProcess::class, + [ + 'paymentMethodList' => $this->paymentMethodList, + 'storeManager' => $this->storeManager + ] + ); + } + + /** + * @param array $jsLayout + * @param array $activePaymentList + * @param array $expectedResult + * @dataProvider beforeProcessDataProvider + */ + public function testBeforeProcess($jsLayout, $activePaymentList, $expectedResult) + { + $this->store->expects($this->once())->method('getId')->willReturn(1); + $this->storeManager->expects($this->once())->method('getStore')->willReturn($this->store); + $this->paymentMethodList->expects($this->once()) + ->method('getActiveList') + ->with(1) + ->willReturn($activePaymentList); + + $result = $this->plugin->beforeProcess($this->layoutProcessor, $jsLayout); + $this->assertEquals($result[0], $expectedResult); + } + + /** + * Data provider for BeforeProcess. + * + * @return array + */ + public function beforeProcessDataProvider() + { + $jsLayout['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = [ + 'braintree' => [ + 'methods' => [ + 'braintree_paypal' => [], + 'braintree' => [] + ] + ], + 'paypal-payments' => [ + 'methods' => [ + 'payflowpro' => [], + 'payflow_link' => [] + ] + ] + ]; + $result1['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = []; + $result2['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = [ + 'braintree' => [ + 'methods' => [ + 'braintree' => [], + 'braintree_paypal' => [] + ] + ] + ]; + + $braintreePaymentMethod = $this + ->getMockBuilder(\Magento\Payment\Api\Data\PaymentMethodInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getCode']) + ->getMockForAbstractClass(); + $braintreePaypalPaymentMethod = $this + ->getMockBuilder(\Magento\Payment\Api\Data\PaymentMethodInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getCode']) + ->getMockForAbstractClass(); + + $braintreePaymentMethod->expects($this->any())->method('getCode')->willReturn('braintree'); + $braintreePaypalPaymentMethod->expects($this->any())->method('getCode')->willReturn('braintree_paypal'); + + return [ + [$jsLayout, [], $result1], + [$jsLayout, [$braintreePaymentMethod, $braintreePaypalPaymentMethod], $result2] + ]; + } +} diff --git a/app/code/Magento/Payment/etc/frontend/di.xml b/app/code/Magento/Payment/etc/frontend/di.xml index 4ff3c013b676523fe20a3deb49f32758c01e604e..471a7ce9e2de585609eb490ada35248c4ee59be3 100644 --- a/app/code/Magento/Payment/etc/frontend/di.xml +++ b/app/code/Magento/Payment/etc/frontend/di.xml @@ -19,4 +19,7 @@ </argument> </arguments> </type> + <type name="Magento\Checkout\Block\Checkout\LayoutProcessor"> + <plugin name="ProcessPaymentConfiguration" type="Magento\Payment\Plugin\PaymentConfigurationProcess"/> + </type> </config> \ No newline at end of file diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml index e0a5471b1e45ee1f6ba9bd8c05d0145656a642ea..0dc555c93d94d3db64e102f24b2fa4e6f45e278f 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml @@ -322,7 +322,7 @@ </item> </argument> </column> - <column name="total_refunded" class="Magento\Sales\Ui\Component\Listing\Column\Price"> + <column name="total_refunded" class="Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">textRange</item> diff --git a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js index 8af48829df438261aaed469c88245fc50a349853..c1d2fd3f910518ddcf15ae50122db3e5f30cd098 100644 --- a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js +++ b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js @@ -6,11 +6,14 @@ define([ 'jquery', 'underscore', + 'mage/template', 'mage/smart-keyboard-handler', + 'mage/translate', + 'priceUtils', 'jquery/ui', 'jquery/jquery.parsequery', 'mage/validation/validation' -], function ($, _, keyboardHandler) { +], function ($, _, mageTemplate, keyboardHandler, $t, priceUtils) { 'use strict'; /** @@ -254,7 +257,13 @@ define([ gallerySwitchStrategy: 'replace', // whether swatches are rendered in product list or on product page - inProductList: false + inProductList: false, + + // tier prise selectors start + tierPriceTemplateSelector: '#tier-prices-template', + tierPriceBlockSelector: '[data-role="tier-price-block"]', + tierPriceTemplate: '' + // tier prise selectors end }, /** @@ -279,6 +288,7 @@ define([ } else { console.log('SwatchRenderer: No input data received'); } + this.options.tierPriceTemplate = $(this.options.tierPriceTemplateSelector).html(); }, /** @@ -809,7 +819,8 @@ define([ $product = $widget.element.parents($widget.options.selectorProduct), $productPrice = $product.find(this.options.selectorProductPrice), options = _.object(_.keys($widget.optionsMap), {}), - result; + result, + tierPriceHtml; $widget.element.find('.' + $widget.options.classes.attributeClass + '[option-selected]').each(function () { var attributeId = $(this).attr('attribute-id'); @@ -825,6 +836,23 @@ define([ 'prices': $widget._getPrices(result, $productPrice.priceBox('option').prices) } ); + + if (result.tierPrices.length) { + if (this.options.tierPriceTemplate) { + tierPriceHtml = mageTemplate( + this.options.tierPriceTemplate, + { + 'tierPrices': result.tierPrices, + '$t': $t, + 'currencyFormat': this.options.jsonConfig.currencyFormat, + 'priceUtils': priceUtils + } + ); + $(this.options.tierPriceBlockSelector).html(tierPriceHtml).show(); + } + } else { + $(this.options.tierPriceBlockSelector).hide(); + } }, /** diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php index 07b9c558043b0ddee1c3b99f63fa0b2f8aa27490..c2c53a3d7754ab080bb9fa818d3cb8d65eac2531 100644 --- a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php +++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php @@ -535,6 +535,7 @@ class CommonTaxCollector extends AbstractTotal $total->setSubtotalInclTax($subtotalInclTax); $total->setBaseSubtotalTotalInclTax($baseSubtotalInclTax); $total->setBaseSubtotalInclTax($baseSubtotalInclTax); + $shippingAssignment->getShipping()->getAddress()->setBaseSubtotalTotalInclTax($baseSubtotalInclTax);; return $this; } diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/select.js b/app/code/Magento/Ui/view/base/web/js/form/element/select.js index 1887639c8d0313fe466aadb89b3cdaf7adc6bd81..4567bba1d017aec81e53dc668b35b4bf696c49d3 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/select.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/select.js @@ -105,7 +105,9 @@ define([ return Abstract.extend({ defaults: { customName: '${ $.parentName }.${ $.index }_input', - elementTmpl: 'ui/form/element/select' + elementTmpl: 'ui/form/element/select', + caption: '', + options: [] }, /** @@ -127,28 +129,6 @@ define([ return this; }, - /** - * Parses options and merges the result with instance - * - * @param {Object} config - * @returns {Object} Chainable. - */ - initConfig: function (config) { - var options = config.options, - captionValue = config.captionValue || '', - result = parseOptions(options, captionValue); - - if (config.caption) { - delete result.caption; - } - - _.extend(config, result); - - this._super(); - - return this; - }, - /** * Calls 'initObservable' of parent, initializes 'options' and 'initialOptions' * properties, calls 'setOptions' passing options to it @@ -160,7 +140,7 @@ define([ this.initialOptions = this.options; - this.observe('options') + this.observe('options caption') .setOptions(this.options()); return this; @@ -209,7 +189,7 @@ define([ return option && option.value; } - if (!this.caption) { + if (!this.caption()) { return findFirst(this.options); } }, @@ -254,14 +234,20 @@ define([ * @returns {Object} Chainable */ setOptions: function (data) { - var isVisible; + var captionValue = this.captionValue || '', + result = parseOptions(data, captionValue), + isVisible; + + this.indexedOptions = indexOptions(result.options); - this.indexedOptions = indexOptions(data); + this.options(result.options); - this.options(data); + if (!this.caption()) { + this.caption(result.caption); + } if (this.customEntry) { - isVisible = !!data.length; + isVisible = !!result.options.length; this.setVisible(isVisible); this.toggleInput(!isVisible); @@ -301,7 +287,7 @@ define([ * @returns {Object} Chainable. */ clear: function () { - var value = this.caption ? '' : findFirst(this.options); + var value = this.caption() ? '' : findFirst(this.options); this.value(value); diff --git a/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php b/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php new file mode 100644 index 0000000000000000000000000000000000000000..db38ccbed417a95870a9da916a64e36b4281353d --- /dev/null +++ b/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php @@ -0,0 +1,93 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Vault\Plugin; + +/** + * Class PaymentVaultConfigurationProcess + * + * Checks if vault group have active vaults. + */ +class PaymentVaultConfigurationProcess +{ + /** + * @var \Magento\Vault\Api\PaymentMethodListInterface + */ + private $vaultPaymentList; + + /** + * @var \Magento\Vault\Api\PaymentMethodListInterface + */ + private $paymentMethodList; + + /** + * @var \Magento\Store\Model\StoreManagerInterface + */ + private $storeManager; + + /** + * @param \Magento\Vault\Api\PaymentMethodListInterface $vaultPaymentList + * @param \Magento\Payment\Api\PaymentMethodListInterface $paymentMethodList + * @param \Magento\Store\Model\StoreManagerInterface $storeManager + */ + public function __construct( + \Magento\Vault\Api\PaymentMethodListInterface $vaultPaymentList, + \Magento\Payment\Api\PaymentMethodListInterface $paymentMethodList, + \Magento\Store\Model\StoreManagerInterface $storeManager + ) { + $this->vaultPaymentList = $vaultPaymentList; + $this->paymentMethodList = $paymentMethodList; + $this->storeManager = $storeManager; + } + + /** + * Checkout LayoutProcessor before process plugin. + * + * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $processor + * @param array $jsLayout + * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforeProcess(\Magento\Checkout\Block\Checkout\LayoutProcessor $processor, $jsLayout) + { + $configuration = &$jsLayout['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children']; + + if (!isset($configuration)) { + return [$jsLayout]; + } + + $storeId = $this->storeManager->getStore()->getId(); + $activePaymentMethodList = $this->paymentMethodList->getActiveList($storeId); + $activeVaultList = $this->vaultPaymentList->getActiveList($storeId); + $getCodeFunc = function ($method) { + return $method->getCode(); + }; + $getProviderCodeFunc = function ($method) { + return $method->getProviderCode(); + }; + $activePaymentMethodCodes = array_map($getCodeFunc, $activePaymentMethodList); + $activeVaultProviderCodes = array_map($getProviderCodeFunc, $activeVaultList); + $activePaymentMethodCodes = array_merge( + $activePaymentMethodCodes, + $activeVaultProviderCodes + ); + + foreach ($configuration as $paymentGroup => $groupConfig) { + $notActivePaymentMethodCodes = array_diff(array_keys($groupConfig['methods']), $activePaymentMethodCodes); + foreach ($notActivePaymentMethodCodes as $notActivePaymentMethodCode) { + unset($configuration[$paymentGroup]['methods'][$notActivePaymentMethodCode]); + } + if ($paymentGroup === 'vault' && !empty($activeVaultProviderCodes)) { + continue; + } + if (empty($configuration[$paymentGroup]['methods'])) { + unset($configuration[$paymentGroup]); + } + } + + return [$jsLayout]; + } +} diff --git a/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultConfigurationProcessTest.php b/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultConfigurationProcessTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7e7a3fd0aebdfcd8054a7276dcce04ec5f49dcb8 --- /dev/null +++ b/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultConfigurationProcessTest.php @@ -0,0 +1,158 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Vault\Test\Unit\Plugin; + +/** + * Class PaymentVaultConfigurationProcessTest. + */ +class PaymentVaultConfigurationProcessTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeManager; + + /** + * @var \Magento\Store\Api\Data\StoreInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $store; + + /** + * @var \Magento\Vault\Api\PaymentMethodListInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $vaultList; + + /** + * @var \Magento\Payment\Api\PaymentMethodListInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $paymentMethodList; + + /** + * @var \Magento\Checkout\Block\Checkout\LayoutProcessor|\PHPUnit_Framework_MockObject_MockObject + */ + private $layoutProcessor; + + /** + * @var \Magento\Vault\Plugin\PaymentVaultConfigurationProcess + */ + private $plugin; + + /** + * Set up + */ + protected function setUp() + { + $this->storeManager = $this + ->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getStore']) + ->getMockForAbstractClass(); + $this->store = $this + ->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getId']) + ->getMockForAbstractClass(); + $this->vaultList = $this + ->getMockBuilder(\Magento\Vault\Api\PaymentMethodListInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getActiveList']) + ->getMockForAbstractClass(); + $this->paymentMethodList = $this + ->getMockBuilder(\Magento\Payment\Api\PaymentMethodListInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getActiveList']) + ->getMockForAbstractClass(); + $this->layoutProcessor = $this + ->getMockBuilder(\Magento\Checkout\Block\Checkout\LayoutProcessor::class) + ->disableOriginalConstructor() + ->setMethods(['process']) + ->getMockForAbstractClass(); + + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->plugin = $objectManagerHelper->getObject( + \Magento\Vault\Plugin\PaymentVaultConfigurationProcess::class, + [ + 'vaultPaymentList' => $this->vaultList, + 'paymentMethodList' => $this->paymentMethodList, + 'storeManager' => $this->storeManager + ] + ); + } + + /** + * @param array $jsLayout + * @param array $activeVaultList + * @param array $activePaymentList + * @param array $expectedResult + * @dataProvider beforeProcessDataProvider + */ + public function testBeforeProcess($jsLayout, $activeVaultList, $activePaymentList, $expectedResult) + { + $this->store->expects($this->once())->method('getId')->willReturn(1); + $this->storeManager->expects($this->once())->method('getStore')->willReturn($this->store); + $this->vaultList->expects($this->once())->method('getActiveList')->with(1)->willReturn($activeVaultList); + $this->paymentMethodList->expects($this->once()) + ->method('getActiveList') + ->with(1) + ->willReturn($activePaymentList); + $result = $this->plugin->beforeProcess($this->layoutProcessor, $jsLayout); + $this->assertEquals($result[0], $expectedResult); + } + + /** + * Data provider for BeforeProcess. + * + * @return array + */ + public function beforeProcessDataProvider() + { + $jsLayout['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = [ + 'vault' => [ + 'methods' => [] + ], + 'braintree' => [ + 'methods' => [ + 'braintree_paypal' => [], + 'braintree' => [] + ] + ], + 'paypal-payments' => [ + 'methods' => [ + 'payflowpro' => [], + 'payflow_link' => [] + ] + ] + ]; + $result1['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = []; + $result2['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = [ + 'vault' => [ + 'methods' => [] + ], + 'braintree' => [ + 'methods' => [ + 'braintree_paypal' => [] + ] + ] + ]; + + $vaultPaymentMethod = $this + ->getMockBuilder(\Magento\Vault\Api\PaymentMethodListInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getCode', 'getProviderCode']) + ->getMockForAbstractClass(); + + $vaultPaymentMethod->expects($this->any())->method('getCode')->willReturn('braintree_paypal_vault'); + $vaultPaymentMethod->expects($this->any())->method('getProviderCode')->willReturn('braintree_paypal'); + + return [ + [$jsLayout, [], [], $result1], + [$jsLayout, [$vaultPaymentMethod], [$vaultPaymentMethod], $result2] + ]; + } +} diff --git a/app/code/Magento/Vault/etc/frontend/di.xml b/app/code/Magento/Vault/etc/frontend/di.xml index d7f699faff53c6e48c6d3d854b265ded269e4dcc..0af0e4cd32217f952d3c49fc7424e99bc8a1ffe0 100644 --- a/app/code/Magento/Vault/etc/frontend/di.xml +++ b/app/code/Magento/Vault/etc/frontend/di.xml @@ -19,4 +19,8 @@ <argument name="session" xsi:type="object">Magento\Customer\Model\Session</argument> </arguments> </type> + <type name="Magento\Checkout\Block\Checkout\LayoutProcessor"> + <plugin name="ProcessPaymentVaultConfiguration" type="Magento\Vault\Plugin\PaymentVaultConfigurationProcess"/> + <plugin name="ProcessPaymentConfiguration" disabled="true"/> + </type> </config> diff --git a/app/code/Magento/Vault/view/adminhtml/web/js/vault.js b/app/code/Magento/Vault/view/adminhtml/web/js/vault.js index 560e65c007f8ab22c2b5b1e76bac0c9062e2af78..66c17801ec02edb262434bc807988bed1bece940 100644 --- a/app/code/Magento/Vault/view/adminhtml/web/js/vault.js +++ b/app/code/Magento/Vault/view/adminhtml/web/js/vault.js @@ -33,8 +33,8 @@ define([ .observe(['active']); // re-init payment method events - self.$selector.off('changePaymentMethod.' + this.code) - .on('changePaymentMethod.' + this.code, this.changePaymentMethod.bind(this)); + self.$selector.off('changePaymentMethod.' + this.getCode()) + .on('changePaymentMethod.' + this.getCode(), this.changePaymentMethod.bind(this)); if (this.active()) { $('#' + this.fieldset + ' input:radio:first').trigger('click'); @@ -50,7 +50,7 @@ define([ * @returns {exports.changePaymentMethod} */ changePaymentMethod: function (event, method) { - this.active(method === this.code); + this.active(method === this.getCode()); return this; }, @@ -61,13 +61,21 @@ define([ */ onActiveChange: function (isActive) { if (!isActive) { - this.$selector.trigger('setVaultNotActive'); + this.$selector.trigger('setVaultNotActive.' + this.getCode()); return; } $('#' + this.fieldset + ' input:radio:first').trigger('click'); - window.order.addExcludedPaymentMethod(this.code); + window.order.addExcludedPaymentMethod(this.getCode()); + }, + + /** + * Get payment method code + * @returns {String} + */ + getCode: function () { + return this.code; } }); }); diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php index 324404ead6c9f5845526512ed6ed39e87f94157c..0f5a0a425a5a5358cf98715827a7950d5e0489fd 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php @@ -237,8 +237,8 @@ class ProductAttributeMediaGalleryManagementInterfaceTest extends \Magento\TestF $targetProduct = $this->getTargetSimpleProduct(); $this->assertEquals('/m/a/magento_image.jpg', $targetProduct->getData('thumbnail')); - $this->assertNull($targetProduct->getData('image')); - $this->assertNull($targetProduct->getData('small_image')); + $this->assertEquals('no_selection', $targetProduct->getData('image')); + $this->assertEquals('no_selection', $targetProduct->getData('small_image')); $mediaGallery = $targetProduct->getData('media_gallery'); $this->assertCount(1, $mediaGallery['images']); $updatedImage = array_shift($mediaGallery['images']); diff --git a/dev/tests/functional/credentials.xml.dist b/dev/tests/functional/credentials.xml.dist index 88794d183e8781d5cea1c9199370c67daae1585c..78186091a568ddba7368126c4b9217714e35d127 100644 --- a/dev/tests/functional/credentials.xml.dist +++ b/dev/tests/functional/credentials.xml.dist @@ -32,10 +32,15 @@ <field path="payment/authorizenet_directpost/trans_key" value="" /> <field path="payment/authorizenet_directpost/trans_md5" value="" /> - <field path="payment/braintree_section/braintree/braintree_advanced/merchant_account_id" value="" /> - <field path="payment/braintree_section/braintree/braintree_required/merchant_id" value="" /> - <field path="payment/braintree_section/braintree/braintree_required/public_key" value="" /> - <field path="payment/braintree_section/braintree/braintree_required/private_key" value="" /> + <field replace="braintree_enabled_fraud_merchant_account_id" value="" /> + <field replace="braintree_enabled_fraud_merchant_id" value="" /> + <field replace="braintree_enabled_fraud_public_key" value="" /> + <field replace="braintree_enabled_fraud_private_key" value="" /> + + <field replace="braintree_disabled_fraud_merchant_account_id" value="" /> + <field replace="braintree_disabled_fraud_merchant_id" value="" /> + <field replace="braintree_disabled_fraud_public_key" value="" /> + <field replace="braintree_disabled_fraud_private_key" value="" /> <field path="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/business_account" value="" /> <field path="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_username" value="" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/ConfigData.xml index 7f01e4f46106c020c10457a8f3e0fb0a7f1de8d7..268ce5795221dbbe3f545891c4d2e420bc87440e 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/ConfigData.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/ConfigData.xml @@ -11,26 +11,26 @@ <field name="payment/braintree_section/braintree/braintree_required/merchant_id" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">PAYMENT_BRAINTREE_MERCHANT_ID</item> - <item name="value" xsi:type="string">PAYMENT_BRAINTREE_MERCHANT_ID</item> + <item name="label" xsi:type="string">Merchant ID</item> + <item name="value" xsi:type="string">%braintree_disabled_fraud_merchant_id%</item> </field> <field name="payment/braintree_section/braintree/braintree_required/public_key" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">PAYMENT_PAYMENT_BRAINTREE_PUBLIC_KEY</item> - <item name="value" xsi:type="string">PAYMENT_PAYMENT_BRAINTREE_PUBLIC_KEY</item> + <item name="label" xsi:type="string">Public Key</item> + <item name="value" xsi:type="string">%braintree_disabled_fraud_public_key%</item> </field> <field name="payment/braintree_section/braintree/braintree_required/private_key" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">PAYMENT_BRAINTREE_PRIVATE_KEY</item> - <item name="value" xsi:type="string">PAYMENT_BRAINTREE_PRIVATE_KEY</item> + <item name="label" xsi:type="string">Private Key</item> + <item name="value" xsi:type="string">%braintree_disabled_fraud_private_key%</item> </field> <field name="payment/braintree_section/braintree/braintree_advanced/merchant_account_id" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">PAYMENT_BRAINTREE_MERCHANT_ACCOUNT_ID</item> - <item name="value" xsi:type="string">PAYMENT_BRAINTREE_MERCHANT_ACCOUNT_ID</item> + <item name="label" xsi:type="string">Merchant Account ID</item> + <item name="value" xsi:type="string">%braintree_disabled_fraud_merchant_account_id%</item> </field> <field name="payment/braintree_section/braintree/braintree_required/payment_action" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -51,6 +51,7 @@ <item name="value" xsi:type="number">1</item> </field> </dataset> + <dataset name="braintree_rollback"> <field name="payment/braintree/active" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -59,6 +60,16 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + + <dataset name="braintree_incorrect_merchant_account_id"> + <field name="payment/braintree_section/braintree/braintree_advanced/merchant_account_id" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Merchant Account ID</item> + <item name="value" xsi:type="string">incorrect</item> + </field> + </dataset> + <dataset name="braintree_sale"> <field name="payment/braintree/payment_action" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -67,6 +78,7 @@ <item name="value" xsi:type="string">authorize_capture</item> </field> </dataset> + <dataset name="braintree_3d_secure"> <field name="payment/braintree_section/braintree/braintree_3dsecure/verify_3dsecure" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -75,6 +87,7 @@ <item name="value" xsi:type="number">1</item> </field> </dataset> + <dataset name="braintree_3d_secure_rollback"> <field name="payment/braintree_section/braintree/braintree_3dsecure/verify_3dsecure" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -83,6 +96,7 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="braintree_3d_secure_uk"> <field name="payment/braintree/verify_3dsecure" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -107,6 +121,7 @@ </item> </field> </dataset> + <dataset name="braintree_3d_secure_uk_rollback"> <field name="payment/braintree_section/braintree/braintree_3dsecure/verify_3dsecure" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -121,6 +136,7 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="braintree_3d_secure_not_triggered_due_threshold"> <field name="payment/braintree/verify_3dsecure" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -135,6 +151,7 @@ <item name="value" xsi:type="number">300</item> </field> </dataset> + <dataset name="braintree_3d_secure_not_triggered_due_threshold_rollback"> <field name="payment/braintree/verify_3dsecure" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -143,6 +160,7 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="braintree_use_vault"> <field name="payment/braintree_section/braintree/braintree_cc_vault_active" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -151,6 +169,7 @@ <item name="value" xsi:type="number">1</item> </field> </dataset> + <dataset name="braintree_use_vault_rollback"> <field name="payment/braintree_section/braintree/braintree_cc_vault_active" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -159,6 +178,7 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="braintree_paypal"> <field name="payment/braintree_section/braintree/active_braintree_paypal" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -173,6 +193,7 @@ <item name="value" xsi:type="string">authorize</item> </field> </dataset> + <dataset name="braintree_paypal_rollback"> <field name="payment/braintree_section/braintree/active_braintree_paypal" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -181,7 +202,14 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="braintree_paypal_sale"> + <field name="payment/braintree_section/braintree/active_braintree_paypal" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="number">1</item> + </field> <field name="payment/braintree_section/braintree/braintree_paypal/payment_action" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> @@ -189,6 +217,16 @@ <item name="value" xsi:type="string">authorize_capture</item> </field> </dataset> + + <dataset name="braintree_paypal_sale_rollback"> + <field name="payment/braintree_section/braintree/active_braintree_paypal" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">No</item> + <item name="value" xsi:type="number">0</item> + </field> + </dataset> + <dataset name="braintree_paypal_skip_order_review"> <field name="payment/braintree_section/braintree/braintree_paypal/skip_order_review" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -197,6 +235,7 @@ <item name="value" xsi:type="number">1</item> </field> </dataset> + <dataset name="braintree_paypal_skip_order_review_rollback"> <field name="payment/braintree_section/braintree/braintree_paypal/skip_order_review" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -205,6 +244,7 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="braintree_paypal_use_vault"> <field name="payment/braintree_section/braintree/braintree_paypal/braintree_paypal_vault_active" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -213,6 +253,7 @@ <item name="value" xsi:type="number">1</item> </field> </dataset> + <dataset name="braintree_paypal_use_vault_rollback"> <field name="payment/braintree_section/braintree/braintree_paypal/braintree_paypal_vault_active" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -221,6 +262,7 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="braintree_fraudprotection"> <field name="payment/braintree/fraudprotection" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -229,6 +271,7 @@ <item name="value" xsi:type="number">1</item> </field> </dataset> + <dataset name="braintree_fraudprotection_rollback"> <field name="payment/braintree/fraudprotection" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -237,5 +280,59 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + + <dataset name="braintree_fraud_tool_enabled_account"> + <field name="payment/braintree_section/braintree/braintree_required/merchant_id" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Merchant ID</item> + <item name="value" xsi:type="string">%braintree_enabled_fraud_merchant_id%</item> + </field> + <field name="payment/braintree_section/braintree/braintree_required/public_key" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Public Key</item> + <item name="value" xsi:type="string">%braintree_enabled_fraud_public_key%</item> + </field> + <field name="payment/braintree_section/braintree/braintree_required/private_key" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Private Key</item> + <item name="value" xsi:type="string">%braintree_enabled_fraud_private_key%</item> + </field> + <field name="payment/braintree_section/braintree/braintree_advanced/merchant_account_id" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Merchant Account ID</item> + <item name="value" xsi:type="string">%braintree_enabled_fraud_merchant_account_id%</item> + </field> + <field name="payment/braintree_section/braintree/braintree_required/payment_action" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Authorize</item> + <item name="value" xsi:type="string">authorize</item> + </field> + <field name="payment/braintree_section/braintree/braintree_advanced/debug" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="number">1</item> + </field> + <field name="payment/braintree_section/braintree/active" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="number">1</item> + </field> + </dataset> + + <dataset name="braintree_fraud_tool_enabled_account_rollback"> + <field name="payment/braintree/active" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">No</item> + <item name="value" xsi:type="number">0</item> + </field> + </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml index e750aa9cb423444e2cc17b8e269a7a62b9289f20..6aa9383ff2bd1051364b1498d799ebb681714aca 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml @@ -13,17 +13,26 @@ <field name="credit_card_exp_year" xsi:type="string">2020</field> <field name="cvv" xsi:type="string">123</field> </dataset> + <dataset name="visa_braintree_3dsecure"> <field name="credit_card_number" xsi:type="string">4000000000000002</field> <field name="credit_card_exp_month" xsi:type="string">01</field> <field name="credit_card_exp_year" xsi:type="string">20</field> <field name="cvv" xsi:type="string">123</field> </dataset> + <dataset name="visa_braintree_3dsecure_failed"> <field name="credit_card_number" xsi:type="string">4000000000000028</field> <field name="credit_card_exp_month" xsi:type="string">01</field> <field name="credit_card_exp_year" xsi:type="string">2020</field> <field name="cvv" xsi:type="string">123</field> </dataset> + + <dataset name="visa_braintree_fraud_rejected"> + <field name="credit_card_number" xsi:type="string">4000111111111511</field> + <field name="credit_card_exp_month" xsi:type="string">01</field> + <field name="credit_card_exp_year" xsi:type="string">2020</field> + <field name="cvv" xsi:type="string">123</field> + </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml index 9614923691c6c097702c3a222bfc52edfcd2489a..083bd33feca7b133903b9f83eb12c4d5b3f1fcfa 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml @@ -64,5 +64,28 @@ <constraint name="Magento\Sales\Test\Constraint\AssertCaptureInCommentsHistory" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" /> </variation> + <variation name="CreateOrderBackendTestBraintreeVariation3" summary="Checkout with Braintree Credit Card from Admin (Basic Fraud Protection)" ticketId="MAGETWO-46470"> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="products/1" xsi:type="string">configurableProduct::with_one_option</data> + <data name="products/2" xsi:type="string">bundleProduct::bundle_fixed_100_dollar_product</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="taxRule" xsi:type="string">us_ca_ny_rule</data> + <data name="billingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="saveAddress" xsi:type="string">No</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="prices" xsi:type="array"> + <item name="grandTotal" xsi:type="string">145.98</item> + </data> + <data name="payment/method" xsi:type="string">braintree</data> + <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_braintree_fraud_rejected</data> + <data name="configData" xsi:type="string">braintree</data> + <data name="status" xsi:type="string">Processing</data> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderSuccessCreateMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" /> + </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDeclinedTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDeclinedTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..4a2aa551a18170002045f821de2d492ddb7a2082 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDeclinedTest.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Checkout\Test\TestCase\OnePageCheckoutDeclinedTest" summary="Error message during OnePageCheckout"> + <variation name="OnePageCheckoutBraintreeDeclinedTestVariation1" summary="Registered Checkout with Braintree Credit Card from Storefront with Advanced Fraud Protection failed" ticketId="MAGETWO-46469"> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="checkoutMethod" xsi:type="string">login</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">braintree</data> + <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_braintree_fraud_rejected</data> + <data name="expectedErrorMessage" xsi:type="string">Transaction has been declined. Please try again later.</data> + <data name="configData" xsi:type="string">braintree_fraud_tool_enabled_account, braintree_fraudprotection</data> + <data name="status" xsi:type="string">Processing</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <constraint name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage" /> + </variation> + <variation name="OnePageCheckoutBraintreeDeclinedTestVariation2" summary="Checkout with Braintree Credit Card configured with incorrect credentials" ticketId="MAGETWO-46244"> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">braintree</data> + <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> + <data name="expectedErrorMessage" xsi:type="string">Sorry, but something went wrong</data> + <data name="configData" xsi:type="string">braintree, braintree_incorrect_merchant_account_id</data> + <data name="status" xsi:type="string">Processing</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <constraint name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml index 920047e7037e135115424a192b9c9cb3267982d5..54fdfc96dc947db330c37b701132bfc0e3fcbeb0 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml @@ -23,7 +23,7 @@ <data name="payment/method" xsi:type="string">braintree</data> <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> <data name="creditCard/dataset" xsi:type="string">visa_braintree_3dsecure</data> - <data name="isVaultEnabled" xsi:type="boolean">false</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> <data name="configData" xsi:type="string">braintree, braintree_3d_secure_not_triggered_due_threshold</data> <data name="status" xsi:type="string">Processing</data> <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> @@ -47,7 +47,7 @@ <data name="payment/method" xsi:type="string">braintree</data> <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> <data name="creditCard/dataset" xsi:type="string">visa_braintree_3dsecure</data> - <data name="isVaultEnabled" xsi:type="boolean">false</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> <data name="configData" xsi:type="string">braintree, braintree_3d_secure_uk</data> <data name="status" xsi:type="string">Processing</data> <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> @@ -71,7 +71,7 @@ <data name="payment/method" xsi:type="string">braintree</data> <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> - <data name="isVaultEnabled" xsi:type="boolean">false</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> <data name="configData" xsi:type="string">braintree</data> <data name="status" xsi:type="string">Processing</data> <data name="tag" xsi:type="string">test_type:extended_acceptance_test, test_type:3rd_party_test, severity:S0</data> @@ -99,7 +99,7 @@ <data name="payment/method" xsi:type="string">braintree</data> <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> - <data name="isVaultEnabled" xsi:type="boolean">false</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> <data name="configData" xsi:type="string">braintree, braintree_sale</data> <data name="status" xsi:type="string">Processing</data> <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureFailedTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureFailedTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0f21b8f219cb13dd426c1aad3cdb0f6ba24b06a6 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureFailedTest.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Braintree\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Preconditions: + * 1. Configure payment method. + * 2. Create products. + * + * Steps: + * 1. Log in Storefront. + * 2. Add products to the Shopping Cart. + * 5. Click the 'Proceed to Checkout' button. + * 6. Fill shipping information. + * 7. Select shipping method. + * 8. Select payment method. + * 9. Verify order total on review step. + * 10. Click 'Place Order' button. + * 11. Specify password in 3D Secure popup. + * 12. Click 'Submit'. + * 13. Perform assertions. + * + * @group Braintree + * @ZephyrId MAGETWO-46477 + */ +class OnePageCheckoutWith3dSecureFailedTest extends Scenario +{ + /* tags */ + const MVP = 'yes'; + const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S1'; + /* end tags */ + + /** + * Verifies error message on Onepage Checkout if 3d secure validation is failed. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureFailedTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureFailedTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..2a17d1496a72dfb1bb63073ccd982abf3522ca9f --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureFailedTest.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Braintree\Test\TestCase\OnePageCheckoutWith3dSecureFailedTest" summary="Onepage checkout with Braintree payment method with 3D Secure enabled."> + <variation name="OnePageCheckoutBraintree3dSecureFailedTestVariation1" summary="Guest Checkout with Braintree Credit Card from Storefront with 3D Secure verification failed" ticketId="MAGETWO-46477"> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">braintree</data> + <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_braintree_3dsecure_failed</data> + <data name="secure3d/dataset" xsi:type="string">secure3d_braintree</data> + <data name="configData" xsi:type="string">braintree, braintree_3d_secure</data> + <data name="expectedErrorMessage" xsi:type="string">Please try again with another form of payment.</data> + <data name="status" xsi:type="string">Processing</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <constraint name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml index ad4d5cc06e92e260aed4c90e6f534f2540d25034..5f5e2f50594bf8d0473b65ee584e50f47bc852a4 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml @@ -7,7 +7,7 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Vault\Test\TestCase\ReorderUsingVaultTest" summary="Reorder from Admin with saved within Braintree credit card"> - <variation name="ReorderUsingVaultBraintreeTestVariation1" summary="Reorder from Admin with saved within Braintree credit card for Guest Customer" ticketId="MAGETWO-54870"> + <variation name="ReorderUsingVaultBraintreeTestVariation1" summary="Reorder from Admin with saved within Braintree credit card for Guest Customer" ticketId="MAGETWO-54869, MAGETWO-54870"> <data name="description" xsi:type="string">Reorder from Admin with saved within Braintree credit card for Guest Customer</data> <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> <data name="customer/dataset" xsi:type="string">default</data> @@ -20,6 +20,7 @@ </data> <data name="payment/method" xsi:type="string">braintree</data> <data name="vault/method" xsi:type="string">braintree_cc_vault</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> <data name="configData" xsi:type="string">braintree, braintree_use_vault</data> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestStep/PlaceOrderWith3dSecureFailedStep.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestStep/PlaceOrderWith3dSecureFailedStep.php new file mode 100644 index 0000000000000000000000000000000000000000..00a8fce571617e5cd643d9b05bd914dc24e3eb43 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestStep/PlaceOrderWith3dSecureFailedStep.php @@ -0,0 +1,55 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Braintree\Test\TestStep; + +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Mtf\TestStep\TestStepInterface; +use Magento\Braintree\Test\Fixture\Secure3dBraintree; + +/** + * Click 'Place order' button and submit 3D secure verification step. + */ +class PlaceOrderWith3dSecureFailedStep implements TestStepInterface +{ + /** + * Onepage checkout page. + * + * @var CheckoutOnepage + */ + private $checkoutOnepage; + + /** + * 3D Secure fixture. + * + * @var Secure3dBraintree + */ + private $secure3d; + + /** + * @param CheckoutOnepage $checkoutOnepage + * @param Secure3dBraintree $secure3d + */ + public function __construct( + CheckoutOnepage $checkoutOnepage, + Secure3dBraintree $secure3d + ) { + $this->checkoutOnepage = $checkoutOnepage; + $this->secure3d = $secure3d; + } + + /** + * Click 'Place order' button and submit 3D secure verification. + * + * @return array + */ + public function run() + { + $this->checkoutOnepage->getPaymentBlock()->getSelectedPaymentMethodBlock()->clickPlaceOrder(); + + $this->checkoutOnepage->getBraintree3dSecureBlock()->fill($this->secure3d); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml index 12aa92d35064d457cef4a544daace01314723d99..6ad46774f0f765b01761f6227465c63b695535d6 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml @@ -21,6 +21,19 @@ <step name="fillBillingInformation" module="Magento_Checkout" next="placeOrderWith3dSecure" /> <step name="placeOrderWith3dSecure" module="Magento_Braintree" /> </scenario> + <scenario name="OnePageCheckoutWith3dSecureFailedTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> + <step name="createProducts" module="Magento_Catalog" next="addProductsToTheCart" /> + <step name="addProductsToTheCart" module="Magento_Checkout" next="proceedToCheckout" /> + <step name="proceedToCheckout" module="Magento_Checkout" next="createCustomer" /> + <step name="createCustomer" module="Magento_Customer" next="selectCheckoutMethod" /> + <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress" /> + <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" /> + <step name="fillShippingMethod" module="Magento_Checkout" next="selectPaymentMethod" /> + <step name="selectPaymentMethod" module="Magento_Checkout" next="fillBillingInformation" /> + <step name="fillBillingInformation" module="Magento_Checkout" next="placeOrderWith3dSecureFailed" /> + <step name="placeOrderWith3dSecureFailed" module="Magento_Braintree" /> + </scenario> <scenario name="UseVaultWith3dSecureOnCheckoutTest" firstStep="setupConfiguration"> <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> <step name="createProducts" module="Magento_Catalog" next="addProductsToTheCart" /> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Links/CompareLink.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Links/CompareLink.php index c81d85a724dcf22ef37e2aa497bf2c6be22f51bd..86c30f4caf8a4ccb10bd7cdebc5f5b8137bfa6b2 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Links/CompareLink.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Links/CompareLink.php @@ -20,6 +20,13 @@ class CompareLink extends Block */ protected $qtyCompareProducts = '.compare .counter.qty'; + /** + * Locator value for Compare Products link. + * + * @var string + */ + protected $linkCompareProducts = '[data-role="compare-products-link"] a.compare'; + /** * Get qty of Products in Compare list. * @@ -32,4 +39,14 @@ class CompareLink extends Block preg_match_all('/^\d+/', $compareProductLink->getText(), $matches); return $matches[0][0]; } + + /** + * Wait for compare products link to appear + * + * @return void + */ + public function waitForCompareProductsLinks() + { + $this->waitForElementVisible($this->linkCompareProducts); + } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View.php index de6adb0efd8b21df23cf0531624fa0b90983225d..5baf4a4cb7c3e273588d85c1217e6824cdefad92 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View.php @@ -522,14 +522,16 @@ class View extends AbstractConfigureBlock } /** - * Check id media gallery is visible for the product. + * Check if media gallery is visible for the product. * * @return bool */ public function isGalleryVisible() { $this->waitForElementNotVisible($this->galleryLoader); - return $this->_rootElement->find($this->mediaGallery)->isVisible(); + $this->waitForElementVisible($this->mediaGallery); + + return true; } /** diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductPage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductPage.php index e99b63d5b8ce7727b93cc3ef2898ef6ba95caf01..fd6f99d13f40fb8bce3f99142d6004f8652087d1 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductPage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductPage.php @@ -31,6 +31,11 @@ class AssertProductPage extends AbstractAssertForm */ protected $product; + /** + * @var CatalogProductView + */ + protected $pageView; + /** * Assert that displayed product data on product page(front-end) equals passed from fixture: * 1. Product Name @@ -53,6 +58,7 @@ class AssertProductPage extends AbstractAssertForm $browser->open($_ENV['app_frontend_url'] . $product->getUrlKey() . '.html'); $this->product = $product; + $this->pageView = $catalogProductView; $this->productView = $catalogProductView->getViewBlock(); $errors = $this->verify(); diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple/CheckoutData.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple/CheckoutData.xml index 180da27ca2a099ab36c00473ac35572c45a31ffd..a1f34f46b0a7cb89342a17a382a0ba1c86de9059 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple/CheckoutData.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple/CheckoutData.xml @@ -137,6 +137,14 @@ </field> </dataset> + <dataset name="simple_order_tier_price_5"> + <field name="qty" xsi:type="string">5</field> + <field name="cartItem" xsi:type="array"> + <item name="price" xsi:type="string">40</item> + <item name="subtotal" xsi:type="string">40</item> + </field> + </dataset> + <dataset name="simple_order_10_dollar_product"> <field name="qty" xsi:type="string">1</field> <field name="cartItem" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Login.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Login.php index 49b900e4eedce313df7809a574e150f3c63c4787..507bb5673effc80e7525b238d0b14b2ee6d40c11 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Login.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Login.php @@ -6,6 +6,7 @@ namespace Magento\Checkout\Test\Block\Onepage; use Magento\Checkout\Test\Fixture\Checkout; +use Magento\Customer\Test\Fixture\Customer; use Magento\Mtf\Block\Form; use Magento\Mtf\Fixture\FixtureInterface; @@ -93,14 +94,15 @@ class Login extends Form /** * Fill required fields for guest checkout. * - * @param FixtureInterface $customer + * @param Customer $customer * @return void */ - public function fillGuestFields(FixtureInterface $customer) + public function fillGuestFields(Customer $customer) { $mapping = $this->dataMapping(); $this->_rootElement->find($mapping['email']['selector'], $mapping['email']['strategy']) ->setValue($customer->getEmail()); + $this->waitForElementNotVisible($this->loadingMask); } /** 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 cce29d23f63b18fc2c469e3df964cb2dd81188e0..24bddf79c1a07c9205e0b22426946e11b92d0489 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 @@ -22,26 +22,49 @@ class Method extends Block protected $shippingMethod = './/tbody//tr[td[contains(., "%s")] and td[contains(., "%s")]]//input'; /** - * Continue checkout button + * Continue checkout button. * * @var string */ protected $continue = '#shipping-method-buttons-container button'; /** - * Wait element + * Wait element. * * @var string */ protected $waitElement = '.loading-mask'; /** - * Block wait element + * Block wait element. * * @var string */ protected $blockWaitElement = '._block-content-loading'; + /** + * Wait until shipping rates will appear. + * + * @return void + */ + private function waitForShippingRates() + { + // Code under test uses JavaScript setTimeout at this point as well. + sleep(3); + $this->waitForElementNotVisible($this->blockWaitElement); + } + + /** + * Retrieve if the shipping methods loader appears. + * + * @return bool|null + */ + public function isLoaderAppeared() + { + $this->_rootElement->click(); + return $this->waitForElementVisible($this->waitElement); + } + /** * Select shipping method. * @@ -50,15 +73,26 @@ 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(); } /** - * Click continue button + * Check whether shipping method is available in the shipping rates. + * + * @param array $method + * @return bool + */ + public function isShippingMethodAvaiable(array $method) + { + $this->waitForShippingRates(); + $selector = sprintf($this->shippingMethod, $method['shipping_method'], $method['shipping_service']); + return $this->_rootElement->find($selector, Locator::SELECTOR_XPATH)->isVisible(); + } + + /** + * Click continue button. * * @return void */ diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCheckoutErrorMessage.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCheckoutErrorMessage.php new file mode 100644 index 0000000000000000000000000000000000000000..24fc2419721b51e3b16c4bcc25e88d13497591c2 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCheckoutErrorMessage.php @@ -0,0 +1,42 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Test\Constraint; + +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Assert that error message is correct. + */ +class AssertCheckoutErrorMessage extends AbstractConstraint +{ + /** + * Assert that error message is correct. + * + * @param CheckoutOnepage $checkoutOnepage + * @param string $expectedErrorMessage + * @return void + */ + public function processAssert(CheckoutOnepage $checkoutOnepage, $expectedErrorMessage) + { + \PHPUnit_Framework_Assert::assertEquals( + $expectedErrorMessage, + $checkoutOnepage->getMessagesBlock()->getErrorMessage(), + 'Wrong error message is displayed.' + ); + } + + /** + * Returns string representation of successful assertion. + * + * @return string + */ + public function toString() + { + return 'Error message on Checkout onepage page is correct.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Page/CheckoutOnepage.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/Page/CheckoutOnepage.xml index 0ab3bbb2c2cfcb01330fecd582bb235ed7805068..00ac573da2e7e658b2dc3a9de50a7185bb2512fb 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Page/CheckoutOnepage.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Page/CheckoutOnepage.xml @@ -17,7 +17,7 @@ <block name="paymentBlock" class="Magento\Checkout\Test\Block\Onepage\Payment" locator="#checkout-step-payment" strategy="css selector" /> <block name="discountCodesBlock" class="Magento\Checkout\Test\Block\Onepage\Payment\DiscountCodes" locator=".discount-code" strategy="css selector" /> <block name="reviewBlock" class="Magento\Checkout\Test\Block\Onepage\Review" locator=".opc-block-summary" strategy="css selector" /> - <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator=".page.messages" strategy="css selector" /> + <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator="//*[@id='checkout']//div[@data-role='checkout-messages' and .//div]" strategy="xpath" /> <block name="customAddressBlock" class="Magento\Checkout\Test\Block\Onepage\CustomAddress" locator=".checkout-billing-address" strategy="css selector" /> </page> </config> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutDeclinedTest.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutDeclinedTest.php new file mode 100644 index 0000000000000000000000000000000000000000..990c3df13e9b1f00e6a2171dfb8f2216b38f0ec3 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutDeclinedTest.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Preconditions: + * 1. Configure payment method. + * 2. Create products. + * + * Steps: + * 1. Log in Storefront. + * 2. Add products to the Shopping Cart. + * 3. Click the 'Proceed to Checkout' button. + * 4. Fill shipping information. + * 5. Select shipping method. + * 6. Select payment method. + * 7. Click 'Place Order' button. + * 8. Perform assertions. + * + * @group Checkout + * @ZephyrId MAGETWO-46469 + */ +class OnePageCheckoutDeclinedTest extends Scenario +{ + /* tags */ + const MVP = 'yes'; + const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S1'; + /* end tags */ + + /** + * Verifies error message on Onepage Checkout. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/ClickPlaceOrderButtonStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/ClickPlaceOrderButtonStep.php new file mode 100644 index 0000000000000000000000000000000000000000..cf086e55d5a305f716f4b64513190b32c7708cba --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/ClickPlaceOrderButtonStep.php @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Test\TestStep; + +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Mtf\TestStep\TestStepInterface; + +/** + * Click 'Place order' button. + */ +class ClickPlaceOrderButtonStep implements TestStepInterface +{ + /** + * Onepage checkout page. + * + * @var CheckoutOnepage + */ + private $checkoutOnepage; + + /** + * @param CheckoutOnepage $checkoutOnepage + */ + public function __construct(CheckoutOnepage $checkoutOnepage) + { + $this->checkoutOnepage = $checkoutOnepage; + } + + /** + * Click 'Place order' button. + * + * @return array + */ + public function run() + { + $this->checkoutOnepage->getPaymentBlock()->getSelectedPaymentMethodBlock()->clickPlaceOrder(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/SelectCheckoutMethodStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/SelectCheckoutMethodStep.php index cb32e5f0ddfe61d9e97e8ef211ce71bfa46ee71a..3af915e22bfcb1c85ebb53b84872ef4ed255fac2 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/SelectCheckoutMethodStep.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/SelectCheckoutMethodStep.php @@ -59,13 +59,6 @@ class SelectCheckoutMethodStep implements TestStepInterface */ private $customerAccountCreatePage; - /** - * Shipping carrier and method. - * - * @var array - */ - protected $shipping; - /** * @constructor * @param CheckoutOnepage $checkoutOnepage @@ -74,7 +67,6 @@ class SelectCheckoutMethodStep implements TestStepInterface * @param LogoutCustomerOnFrontendStep $logoutCustomerOnFrontend * @param ClickProceedToCheckoutStep $clickProceedToCheckoutStep * @param string $checkoutMethod - * @param array $shipping */ public function __construct( CheckoutOnepage $checkoutOnepage, @@ -82,8 +74,7 @@ class SelectCheckoutMethodStep implements TestStepInterface Customer $customer, LogoutCustomerOnFrontendStep $logoutCustomerOnFrontend, ClickProceedToCheckoutStep $clickProceedToCheckoutStep, - $checkoutMethod, - array $shipping = [] + $checkoutMethod ) { $this->checkoutOnepage = $checkoutOnepage; $this->customerAccountCreatePage = $customerAccountCreatePage; @@ -91,7 +82,6 @@ class SelectCheckoutMethodStep implements TestStepInterface $this->logoutCustomerOnFrontend = $logoutCustomerOnFrontend; $this->clickProceedToCheckoutStep = $clickProceedToCheckoutStep; $this->checkoutMethod = $checkoutMethod; - $this->shipping = $shipping; } /** @@ -120,9 +110,7 @@ class SelectCheckoutMethodStep implements TestStepInterface $this->checkoutOnepage->getLoginBlock()->loginCustomer($this->customer); } } elseif ($this->checkoutMethod === 'guest') { - if (empty($this->shipping)) { - $this->checkoutOnepage->getLoginBlock()->fillGuestFields($this->customer); - } + $this->checkoutOnepage->getLoginBlock()->fillGuestFields($this->customer); } elseif ($this->checkoutMethod === 'sign_in') { $this->checkoutOnepage->getAuthenticationWrapperBlock()->signInLinkClick(); $this->checkoutOnepage->getAuthenticationWrapperBlock()->loginCustomer($this->customer); diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/di.xml index 24b369200e71d99df604457603969594b40862ca..d7a61b0eaaa2fece41b7d1f464f0e56bdb80d159 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/di.xml @@ -22,4 +22,9 @@ <argument name="severity" xsi:type="string">S0</argument> </arguments> </type> + <type name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage"> + <arguments> + <argument name="severity" xsi:type="string">S1</argument> + </arguments> + </type> </config> 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 24eb96c0a9347741384ffd6718bf349eeb452c85..e9b49babbba1936aae49b20339a56732b5b2531b 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,17 @@ <step name="addProductsToTheCart" module="Magento_Checkout" next="ProceedToCheckout" /> <step name="ProceedToCheckout" module="Magento_Checkout" /> </scenario> + <scenario name="OnePageCheckoutDeclinedTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> + <step name="createProducts" module="Magento_Catalog" next="addProductsToTheCart" /> + <step name="addProductsToTheCart" module="Magento_Checkout" next="proceedToCheckout" /> + <step name="proceedToCheckout" module="Magento_Checkout" next="createCustomer" /> + <step name="createCustomer" module="Magento_Customer" next="selectCheckoutMethod" /> + <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress" /> + <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" /> + <step name="fillShippingMethod" module="Magento_Checkout" next="selectPaymentMethod" /> + <step name="selectPaymentMethod" module="Magento_Checkout" next="fillBillingInformation" /> + <step name="fillBillingInformation" module="Magento_Checkout" next="clickPlaceOrderButton" /> + <step name="clickPlaceOrderButton" module="Magento_Checkout" /> + </scenario> </config> diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFilteringTest.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFilteringTest.xml index 715190039162b4fdbab91af72ca564e0c0732858..0b237e506636cf1beb8ff22122c515079cda176e 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFilteringTest.xml +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFilteringTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridFilteringTest" summary="Grid UI Component Filtering" ticketId="MAGETWO-41329"> <variation name="CmsPageGridFiltering"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S3</data> <data name="description" xsi:type="string">Verify cms page grid filtering</data> <data name="itemsCount" xsi:type="string">2</data> <data name="fixtureName" xsi:type="string">cmsPage</data> @@ -29,7 +29,7 @@ <constraint name="\Magento\Ui\Test\Constraint\AssertGridFiltering"/> </variation> <variation name="CmsBlockGridFiltering"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S3</data> <data name="description" xsi:type="string">Verify cms block grid filtering</data> <data name="itemsCount" xsi:type="string">2</data> <data name="fixtureName" xsi:type="string">cmsBlock</data> diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFullTextSearchTest.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFullTextSearchTest.xml index fc279aad59d3d7e21590be2c256f83831e7295cf..b17f32db04b23727a6583db5227dbf79d0f0d19d 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFullTextSearchTest.xml +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFullTextSearchTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridFullTextSearchTest" summary="Grid UI Component Full Text Search" ticketId="MAGETWO-41023"> <variation name="CmsPageGridFullTextSearch"> - <data name="tag" xsi:type="string">severity:S2, stable:no</data> + <data name="tag" xsi:type="string">severity:S3, stable:no</data> <data name="description" xsi:type="string">Verify cms page grid full text search</data> <data name="itemsCount" xsi:type="string">2</data> <data name="fixtureName" xsi:type="string">cmsPage</data> @@ -20,7 +20,7 @@ <constraint name="Magento\Ui\Test\Constraint\AssertGridFullTextSearch"/> </variation> <variation name="CmsBlockGridFullTextSearch"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S3</data> <data name="description" xsi:type="string">Verify cms blocks grid full text search</data> <data name="itemsCount" xsi:type="string">2</data> <data name="fixtureName" xsi:type="string">cmsBlock</data> diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridSortingTest.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridSortingTest.xml index 1be7e61f6bd0ea27a99733a63828f438ab481215..053d32a0598ef1677cf67c83c307aa2352ac7803 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridSortingTest.xml +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridSortingTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridSortingTest" summary="Grid UI Component Sorting" ticketId="MAGETWO-41328"> <variation name="CmsPagesGridSorting"> - <data name="tag" xsi:type="string">severity:S2, stable:no</data> + <data name="tag" xsi:type="string">severity:S3, stable:no</data> <data name="description" xsi:type="string">Verify cms page grid sorting</data> <data name="columnsForSorting" xsi:type="array"> <item name="id" xsi:type="string">ID</item> @@ -19,7 +19,7 @@ <constraint name="Magento\Ui\Test\Constraint\AssertGridSorting"/> </variation> <variation name="CmsBlocksGridSorting"> - <data name="tag" xsi:type="string">severity:S2, stable:no</data> + <data name="tag" xsi:type="string">severity:S3, stable:no</data> <data name="description" xsi:type="string">Verify cms blocks grid sorting</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="string">-</item> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Product/View/ConfigurableOptions.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Product/View/ConfigurableOptions.php index d5279557ec5af84902fbc2a57548df2dcf0aadf6..4edee00a57dbefd8a15846731fa7e888b66186ad 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Product/View/ConfigurableOptions.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Product/View/ConfigurableOptions.php @@ -34,6 +34,13 @@ class ConfigurableOptions extends CustomOptions */ protected $priceBlock = '//*[@class="product-info-main"]//*[contains(@class,"price-box")]'; + /** + * Selector for tier prices. + * + * @var string + */ + private $tierPricesSelector = '.prices-tier li'; + /** * Get configurable product options * @@ -93,11 +100,16 @@ class ConfigurableOptions extends CustomOptions } $productVariations = array_keys($productVariations); - $result = []; foreach ($productVariations as $variation) { $variationOptions = explode(' ', $variation); - $result[$variation]['price'] = $this->getOptionPrice($variationOptions, $attributesData); + //Select all options specified in variation + $this->chooseOptions($variationOptions, $attributesData); + $result[$variation]['price'] = $this->getOptionPrice(); + $tierPrices = $this->getOptionTierPrices(); + if (count($tierPrices) > 0) { + $result[$variation]['tierPrices'] = $tierPrices; + } } return $result; @@ -106,25 +118,34 @@ class ConfigurableOptions extends CustomOptions /** * Get option price * - * @param array $variationOptions - * @param array $attributesData * @return null|string */ - protected function getOptionPrice($variationOptions, $attributesData) + protected function getOptionPrice() { - //Select all options specified in variation - foreach ($variationOptions as $variationSelection) { - list ($attribute, $option) = explode(':', $variationSelection); - $attributeTitle = $attributesData[$attribute]['label']; - $optionTitle = $attributesData[$attribute]['options'][$option]['label']; - $this->selectOption($attributeTitle, $optionTitle); - } - $priceBlock = $this->getPriceBlock(); $price = ($priceBlock->isOldPriceVisible()) ? $priceBlock->getOldPrice() : $priceBlock->getPrice(); return $price; } + /** + * Get tier prices of all variations + * + * @return array + */ + private function getOptionTierPrices() + { + $prices = []; + $tierPricesNodes = $this->_rootElement->getElements($this->tierPricesSelector); + foreach ($tierPricesNodes as $node) { + preg_match('#^[^\d]+(\d+)[^\d]+(\d+(?:(?:,\d+)*)+(?:.\d+)*).*#i', $node->getText(), $matches); + $prices[] = [ + 'qty' => isset($matches[1]) ? $matches[1] : null, + 'price_qty' => isset($matches[2]) ? $matches[2] : null, + ]; + } + return $prices; + } + /** * Get block price. * @@ -139,6 +160,8 @@ class ConfigurableOptions extends CustomOptions } /** + * Select option from the select element. + * * @param string $attributeTitle * @param string $optionTitle */ @@ -147,4 +170,22 @@ class ConfigurableOptions extends CustomOptions $this->_rootElement->find(sprintf($this->optionSelector, $attributeTitle), Locator::SELECTOR_XPATH, 'select') ->setValue($optionTitle); } + + /** + * Choose options of the configurable product + * + * @param $variationOptions + * @param $attributesData + * @return void + */ + protected function chooseOptions($variationOptions, $attributesData) + { + //Select all options specified in variation + foreach ($variationOptions as $variationSelection) { + list ($attribute, $option) = explode(':', $variationSelection); + $attributeTitle = $attributesData[$attribute]['label']; + $optionTitle = $attributesData[$attribute]['options'][$option]['label']; + $this->selectOption($attributeTitle, $optionTitle); + } + } } diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductTierPriceOnProductPage.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductTierPriceOnProductPage.php new file mode 100644 index 0000000000000000000000000000000000000000..74c885a727880edffd79717f5f30689135a3704d --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductTierPriceOnProductPage.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\ConfigurableProduct\Test\Constraint; + +use Magento\Catalog\Test\Constraint\AssertProductPage; +use Magento\ConfigurableProduct\Test\Block\Product\View\ConfigurableOptions; + +/** + * Open created configurble product on frontend and choose variation with tier price + */ +class AssertProductTierPriceOnProductPage extends AssertProductPage +{ + /** + * Verify that tier prices configured for all variations of configured product displayed as expected. + * + * @return array + */ + public function verify() + { + $errors = []; + /** @var ConfigurableOptions $optionsBlock */ + $optionsBlock = $this->pageView->getConfigurableAttributesBlock(); + $formTierPrices = $optionsBlock->getOptionsPrices($this->product); + $products = ($this->product->getDataFieldConfig('configurable_attributes_data')['source'])->getProducts(); + foreach ($products as $key => $product) { + $configuredTierPrice = []; + $actualTierPrices = isset($formTierPrices[$key]['tierPrices']) ? $formTierPrices[$key]['tierPrices'] : []; + $tierPrices = $product->getTierPrice() ?: []; + foreach ($tierPrices as $tierPrice) { + $configuredTierPrice[] = [ + 'qty' => $tierPrice['price_qty'], + 'price_qty' => $tierPrice['price'], + ]; + } + + if ($configuredTierPrice != $actualTierPrices) { + $errors[] = sprintf('Tier prices for variation %s doesn\'t equals to configured.', $key); + } + } + + return $errors; + } +} diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php index 65f80eb7144638b59e61a984c27582a316e9b129..65715d116ab45780dcacae89ef987a16e9127ceb 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php @@ -277,10 +277,12 @@ class ConfigurableAttributesData extends DataSource $variationsMatrix = $this->addVariationMatrix($variationsMatrix, $attribute, $attributeKey); } - foreach ($data['matrix'] as $key => $value) { - if (isset($value['sku']) && $value['sku'] === '') { - unset($variationsMatrix[$key]['sku']); - unset($data['matrix'][$key]['sku']); + if (isset($data['matrix'])) { + foreach ($data['matrix'] as $key => $value) { + if (isset($value['sku']) && $value['sku'] === '') { + unset($variationsMatrix[$key]['sku']); + unset($data['matrix'][$key]['sku']); + } } } diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Product/CatalogProductView.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Product/CatalogProductView.xml index c2c5d8428b480dd5ccae46f67d2065bc203b8331..c825f733de1790ef5e8f0a81ad38c37a493df12f 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Product/CatalogProductView.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Product/CatalogProductView.xml @@ -10,6 +10,6 @@ <block name="viewBlock"> <render name="configurable" class="Magento\ConfigurableProduct\Test\Block\Product\View"/> </block> - <block name="configurableAttributesBlock" class="Magento\ConfigurableProduct\Test\Block\Product\View\ConfigurableOptions" locator="#product-options-wrapper" strategy="css selector"/> + <block name="configurableAttributesBlock" class="Magento\ConfigurableProduct\Test\Block\Product\View\ConfigurableOptions" locator=".product-info-main" strategy="css selector"/> </page> </config> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/CheckoutData.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/CheckoutData.xml index bb9f7a4ae03b19500b954e187a8765121579acf7..949c6dc065c494a18e2ae617ef859f6663dd05d4 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/CheckoutData.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/CheckoutData.xml @@ -154,6 +154,22 @@ </field> </dataset> + <dataset name="configurable_two_new_options_with_tier_price"> + <field name="options" xsi:type="array"> + <item name="configurable_options" xsi:type="array"> + <item name="0" xsi:type="array"> + <item name="title" xsi:type="string">attribute_key_0</item> + <item name="value" xsi:type="string">option_key_1</item> + </item> + </item> + </field> + <field name="cartItem" xsi:type="array"> + <item name="price" xsi:type="string">9</item> + <item name="qty" xsi:type="string">1</item> + <item name="subtotal" xsi:type="string">9</item> + </field> + </dataset> + <dataset name="configurable_two_options_with_assigned_product"> <field name="options" xsi:type="array"> <item name="configurable_options" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/ConfigurableAttributesData.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/ConfigurableAttributesData.xml index cf9d73d3dcd2e727dc7cdb290ecf74d17a453c31..44e2e14545db02103bfe2fa2613f196937cfc558 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/ConfigurableAttributesData.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/ConfigurableAttributesData.xml @@ -440,6 +440,42 @@ </field> </dataset> + <dataset name="two_options_with_assigned_product_tier_price"> + <field name="attributes_data" xsi:type="array"> + <item name="attribute_key_0" xsi:type="array"> + <item name="options" xsi:type="array"> + <item name="option_key_0" xsi:type="array"> + <item name="label" xsi:type="string">option_key_1_%isolation%</item> + <item name="pricing_value" xsi:type="string">560</item> + <item name="include" xsi:type="string">Yes</item> + </item> + <item name="option_key_1" xsi:type="array"> + <item name="label" xsi:type="string">option_key_2_%isolation%</item> + <item name="pricing_value" xsi:type="string">10</item> + <item name="include" xsi:type="string">Yes</item> + </item> + </item> + </item> + </field> + <field name="attributes" xsi:type="array"> + <item name="attribute_key_0" xsi:type="string">catalogProductAttribute::attribute_type_dropdown_two_options</item> + </field> + <field name="products" xsi:type="array"> + <item name="attribute_key_0:option_key_0" xsi:type="string">catalogProductSimple::default</item> + <item name="attribute_key_0:option_key_1" xsi:type="string">catalogProductSimple::simple_with_tier_price</item> + </field> + <field name="matrix" xsi:type="array"> + <item name="attribute_key_0:option_key_0" xsi:type="array"> + <item name="qty" xsi:type="string">10</item> + <item name="weight" xsi:type="string">1</item> + </item> + <item name="attribute_key_0:option_key_1" xsi:type="array"> + <item name="qty" xsi:type="string">20</item> + <item name="weight" xsi:type="string">1</item> + </item> + </field> + </dataset> + <dataset name="color_and_size"> <field name="attributes_data" xsi:type="array"> <item name="attribute_key_0" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml index 14ff24f18908da187a0631662cf74bfdaad5db6f..42277101cfbdaf5622efb6b4347dafb75bb113aa 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml @@ -159,5 +159,19 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductOnCustomWebsite" /> </variation> + <variation name="CreateConfigurableProductEntityTestVariation10" summary="Create configurable product with tier price for one item"> + <data name="product/data/url_key" xsi:type="string">configurable-product-%isolation%</data> + <data name="product/data/configurable_attributes_data/dataset" xsi:type="string">two_options_with_assigned_product_tier_price</data> + <data name="product/data/checkout_data/dataset" xsi:type="string">configurable_two_new_options_with_special_price</data> + <data name="product/data/name" xsi:type="string">Configurable Product %isolation%</data> + <data name="product/data/sku" xsi:type="string">configurable_sku_%isolation%</data> + <data name="product/data/price/value" xsi:type="string">1</data> + <data name="product/data/weight" xsi:type="string">2</data> + <data name="product/data/category_ids/dataset" xsi:type="string">default_subcategory</data> + <data name="product/data/short_description" xsi:type="string">Configurable short description</data> + <data name="product/data/description" xsi:type="string">Configurable Product description %isolation%</data> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" /> + <constraint name="Magento\ConfigurableProduct\Test\Constraint\AssertProductTierPriceOnProductPage" /> + </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.xml index 8baa7ce0d9310f7e2d7a17fab8c904530cf25629..ba85d0d13bfc68761ea562802f259dcda28ff738 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.xml @@ -241,6 +241,40 @@ <field name="telephone" xsi:type="string">333-33-333-33</field> </dataset> + <dataset name="DE_address_Frankfurt"> + <field name="firstname" xsi:type="string">Jan</field> + <field name="lastname" xsi:type="string">Jansen</field> + <field name="company" xsi:type="string">Magento %isolation%</field> + <field name="city" xsi:type="string">Frankfurt</field> + <field name="street" xsi:type="string">Marzellenstrasse 13-17</field> + <field name="postcode" xsi:type="string">10789</field> + <field name="country_id" xsi:type="string">Germany</field> + <field name="region" xsi:type="string">Hessen</field> + <field name="telephone" xsi:type="string">333-33-333-33</field> + </dataset> + + <dataset name="KE_Nairobi"> + <field name="firstname" xsi:type="string">John</field> + <field name="lastname" xsi:type="string">Doe</field> + <field name="company" xsi:type="string">Magento %isolation%</field> + <field name="city" xsi:type="string">Nairobi</field> + <field name="street" xsi:type="string">6161 West Centinela Avenue</field> + <field name="telephone" xsi:type="string">555-55-555-55</field> + <field name="country_id" xsi:type="string">Kenya</field> + <field name="postcode" xsi:type="string">12345</field> + </dataset> + + <dataset name="KE_Mombasa"> + <field name="firstname" xsi:type="string">John</field> + <field name="lastname" xsi:type="string">Doe</field> + <field name="company" xsi:type="string">Magento %isolation%</field> + <field name="city" xsi:type="string">Mombasa</field> + <field name="street" xsi:type="string">6161 West Centinela Avenue</field> + <field name="telephone" xsi:type="string">555-55-555-55</field> + <field name="country_id" xsi:type="string">Kenya</field> + <field name="postcode" xsi:type="string">12345</field> + </dataset> + <dataset name="customer_UK_US_addresses"> <field name="firstname" xsi:type="string">John</field> <field name="lastname" xsi:type="string">Doe%isolation%</field> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFilteringTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFilteringTest.xml index 918f723981faac5a3a919caaf99ac9e75b0bf1bd..42a3103ce33d7615fcbfd06084bebfa965769b60 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFilteringTest.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFilteringTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridFilteringTest" summary="Grid UI Component Filtering" ticketId="MAGETWO-41329"> <variation name="CustomerGridFiltering"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="description" xsi:type="string">Verify customer page grid filtering</data> <data name="itemsCount" xsi:type="string">2</data> <data name="fixtureName" xsi:type="string">customer</data> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFullTextSearchTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFullTextSearchTest.xml index 00a2955be126a67b96d6ff8b03c706fe3b98d802..ef0bf7b7cea72e941840f103bb3700d66f06404c 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFullTextSearchTest.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFullTextSearchTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridFullTextSearchTest" summary="Grid UI Component Full Text Search" ticketId="MAGETWO-41023"> <variation name="CustomerGridFullTextSearch"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="description" xsi:type="string">Verify customer page grid full text search</data> <data name="itemsCount" xsi:type="string">2</data> <data name="fixtureName" xsi:type="string">customer</data> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridSortingTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridSortingTest.xml index b967fbd184526fd1d71fcf2055799842d0d018f1..7d6e7f6d8f1b4f3a2402e0ae1b659f60c941c63d 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridSortingTest.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridSortingTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridSortingTest" summary="Grid UI Component Sorting" ticketId="MAGETWO-41328"> <variation name="CustomerGridSorting"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="tag" xsi:type="string">stable:no</data> <data name="description" xsi:type="string">Verify customer page grid sorting</data> <data name="columnsForSorting" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/Dhl/Test/TestCase/CityBasedShippingRateTest.xml b/dev/tests/functional/tests/app/Magento/Dhl/Test/TestCase/CityBasedShippingRateTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..e54439c8cd05c5537542d1769d58714d89fc4fb2 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Dhl/Test/TestCase/CityBasedShippingRateTest.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Shipping\Test\TestCase\CityBasedShippingRateTest" summary="Shipping rates can be reloaded based on changes in City field value"> + <variation name="CityBasedShippingRateDHLTestVariation" summary="Shipping rates can be reloaded based on changes in City field value for DHL shipping method" ticketId="MAGETWO-56124"> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <data name="products/0" xsi:type="string">catalogProductSimple::default</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingMethod/shipping_service" xsi:type="string">DHL</data> + <data name="shippingMethod/shipping_method" xsi:type="string">Express easy</data> + <data name="clearShippingAddress/postcode" xsi:type="string" /> + <data name="clearShippingAddress/city" xsi:type="string" /> + <data name="clearShippingAddress/country_id" xsi:type="string" /> + <data name="shippingAddresses/0/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/1/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/1/postcode" xsi:type="string">12345</data> + <data name="shippingAddresses/2/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/2/postcode" xsi:type="string">12345</data> + <data name="shippingAddresses/2/city" xsi:type="string">Nairobi</data> + <data name="shippingAddresses/3/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/3/postcode" xsi:type="string">12345</data> + <data name="shippingAddresses/3/city" xsi:type="string">Mombasa</data> + <data name="shippingAddresses/4/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/4/city" xsi:type="string">Mombasa</data> + <data name="shippingAddresses/5/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/5/city" xsi:type="string">Nairobi</data> + <data name="isShippingAvailable" xsi:type="array"> + <item name="0" xsi:type="boolean">false</item> + <item name="1" xsi:type="boolean">false</item> + <item name="2" xsi:type="boolean">true</item> + <item name="3" xsi:type="boolean">true</item> + <item name="4" xsi:type="boolean">true</item> + <item name="5" xsi:type="boolean">true</item> + </data> + <data name="configData" xsi:type="string">dhl_eu, shipping_origin_CH, config_base_currency_ch</data> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Fedex/Test/TestCase/CityBasedShippingRateTest.xml b/dev/tests/functional/tests/app/Magento/Fedex/Test/TestCase/CityBasedShippingRateTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..b6a2fd5776a27d307e7c0f8372438b42f38fd7f5 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Fedex/Test/TestCase/CityBasedShippingRateTest.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Shipping\Test\TestCase\CityBasedShippingRateTest" summary="Shipping rates can be reloaded based on changes in City field value"> + <variation name="CityBasedShippingRateFedexTestVariation" summary="Shipping rates can be reloaded based on changes in City field value for Fedex shipping method" ticketId="MAGETWO-56124"> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <data name="products/0" xsi:type="string">catalogProductSimple::default</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingMethod/shipping_service" xsi:type="string">Federal Express</data> + <data name="shippingMethod/shipping_method" xsi:type="string">International Economy</data> + <data name="clearShippingAddress/postcode" xsi:type="string" /> + <data name="clearShippingAddress/city" xsi:type="string" /> + <data name="clearShippingAddress/country_id" xsi:type="string" /> + <data name="shippingAddresses/0/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/1/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/1/postcode" xsi:type="string">12345</data> + <data name="shippingAddresses/2/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/2/postcode" xsi:type="string">12345</data> + <data name="shippingAddresses/2/city" xsi:type="string">Nairobi</data> + <data name="shippingAddresses/3/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/3/postcode" xsi:type="string">12345</data> + <data name="shippingAddresses/3/city" xsi:type="string">Mombasa</data> + <data name="shippingAddresses/4/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/4/city" xsi:type="string">Mombasa</data> + <data name="shippingAddresses/5/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/5/city" xsi:type="string">Nairobi</data> + <data name="isShippingAvailable" xsi:type="array"> + <item name="0" xsi:type="boolean">false</item> + <item name="1" xsi:type="boolean">true</item> + <item name="2" xsi:type="boolean">true</item> + <item name="3" xsi:type="boolean">true</item> + <item name="4" xsi:type="boolean">false</item> + <item name="5" xsi:type="boolean">false</item> + </data> + <data name="configData" xsi:type="string">fedex, shipping_origin_US_CA</data> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml index f6ac4ac4f0a3c4591c12de7215600010c5fb857c..11f9d9d5270e679df9cd5237b4a51139cb51475e 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml @@ -21,7 +21,7 @@ </data> <data name="creditCardClass" xsi:type="string">credit_card</data> <data name="creditCard/dataset" xsi:type="string">visa_default</data> - <data name="isVaultEnabled" xsi:type="boolean">false</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> <data name="configData" xsi:type="string">payflowpro</data> <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml index b1da43e473bc5d78d4bfaf0fbcbb718dac6acd3e..ad937cf472de7145429b16983288df69bb851134 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml @@ -7,7 +7,7 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Vault\Test\TestCase\ReorderUsingVaultTest" summary="Reorder from Admin with saved within PayPal Payflow Pro credit card"> - <variation name="ReorderUsingVaultPayflowProTestVariation1" summary="Reorder from Admin with saved within PayPal Payflow Pro credit card for Guest Customer" ticketId="MAGETWO-54872"> + <variation name="ReorderUsingVaultPayflowProTestVariation1" summary="Reorder from Admin with saved within PayPal Payflow Pro credit card for Guest Customer" ticketId="MAGETWO-34217, MAGETWO-54872"> <data name="description" xsi:type="string">Reorder from Admin with saved within PayPal Payflow Pro credit card for Guest Customer</data> <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> <data name="customer/dataset" xsi:type="string">default</data> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php index d1f27d14a6619f71fc2e459adad23888d4fb51b7..4b3768295799695fbb45db1a17e75acb193b91f7 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php @@ -9,7 +9,7 @@ namespace Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Invoices; /** * Invoices grid on order view page. */ -class Grid extends \Magento\Backend\Test\Block\Widget\Grid +class Grid extends \Magento\Ui\Test\Block\Adminhtml\DataGrid { /** * Locator value for link in action column. @@ -34,6 +34,9 @@ class Grid extends \Magento\Backend\Test\Block\Widget\Grid 'id' => [ 'selector' => 'input[name="increment_id"]', ], + 'order_id' => [ + 'selector' => 'input[name="order_increment_id"]', + ], 'status' => [ 'selector' => 'select[name="state"]', 'input' => 'select', diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceStatusInOrdersGrid.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceStatusInOrdersGrid.php new file mode 100644 index 0000000000000000000000000000000000000000..6695786923b5c00c71e12101855421554e940281 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceStatusInOrdersGrid.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Constraint; + +use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Assert invoice status on order page in Admin. + */ +class AssertInvoiceStatusInOrdersGrid extends AbstractConstraint +{ + /** + * Assert invoice status on order page in Admin. + * + * @param SalesOrderView $salesOrderView + * @param string $invoiceStatus + * @param string $orderId + * @return void + */ + public function processAssert( + SalesOrderView $salesOrderView, + $invoiceStatus, + $orderId + ) { + $salesOrderView->open(['order_id' => $orderId]); + $salesOrderView->getOrderForm()->openTab('invoices'); + /** @var \Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Invoices\Grid $grid */ + $grid = $salesOrderView->getOrderForm()->getTab('invoices')->getGridBlock(); + $filter = [ + 'order_id' => $orderId, + 'status' => $invoiceStatus, + ]; + \PHPUnit_Framework_Assert::assertTrue( + $grid->isRowVisible($filter), + 'Invoice status is incorrect.' + ); + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString() + { + return 'Invoice status is correct.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFilteringTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFilteringTest.xml index b4c3a7568a2a1dd4fb62fe0d013b6425d372d27d..78c2676765418ebcbbae5ed21a8b0b0cb9ab1da8 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFilteringTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFilteringTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridFilteringTest" summary="Grid UI Component Filtering" ticketId="MAGETWO-41328"> <variation name="SalesOrderGridFiltering"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="tag" xsi:type="string">stable:no</data> <data name="description" xsi:type="string">Verify sales order grid filtering</data> <data name="steps" xsi:type="array"> @@ -33,6 +34,7 @@ <constraint name="\Magento\Ui\Test\Constraint\AssertGridFiltering"/> </variation> <variation name="SalesInvoiceGridFiltering"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="description" xsi:type="string">Verify sales invoice grid filtering</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="string">Magento\Sales\Test\TestStep\CreateInvoiceStep</item> @@ -56,6 +58,7 @@ <constraint name="Magento\Ui\Test\Constraint\AssertGridFiltering"/> </variation> <variation name="SalesShipmentGridFiltering"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="description" xsi:type="string">Verify sales shipment grid filtering</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="string">Magento\Sales\Test\TestStep\CreateShipmentStep</item> @@ -79,6 +82,7 @@ <constraint name="Magento\Ui\Test\Constraint\AssertGridFiltering"/> </variation> <variation name="SalesCreditMemoGridFiltering"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="description" xsi:type="string">Verify sales credit memo grid filtering</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFullTextSearchTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFullTextSearchTest.xml index 0979d0dcbff250a7f0bdb2d5151f60004f72efd0..86278c52a1e26f28c82b799de7a1f45a1f4273e9 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFullTextSearchTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFullTextSearchTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridFullTextSearchTest" summary="Grid UI Component Full Text Search" ticketId="MAGETWO-41023"> <variation name="SalesOrderGridFullTextSearch"> - <data name="tag" xsi:type="string">stable:no</data> + <data name="tag" xsi:type="string">severity:S2, stable:no</data> <data name="description" xsi:type="string">Verify sales order grid full text search</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="string">-</item> @@ -24,7 +24,7 @@ <constraint name="Magento\Ui\Test\Constraint\AssertGridFullTextSearch"/> </variation> <variation name="SalesInvoiceGridFullTextSearch"> - <data name="tag" xsi:type="string">stable:no</data> + <data name="tag" xsi:type="string">severity:S3, stable:no</data> <data name="description" xsi:type="string">Verify sales invoice grid full text search</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="string">Magento\Sales\Test\TestStep\CreateInvoiceStep</item> @@ -41,6 +41,7 @@ <constraint name="Magento\Ui\Test\Constraint\AssertGridFullTextSearch"/> </variation> <variation name="SalesShipmentGridFullTextSearch"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="description" xsi:type="string">Verify sales shipment grid full text search</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="string">Magento\Sales\Test\TestStep\CreateShipmentStep</item> @@ -57,7 +58,7 @@ <constraint name="Magento\Ui\Test\Constraint\AssertGridFullTextSearch"/> </variation> <variation name="SalesCreditMemoGridFullTextSearch"> - <data name="tag" xsi:type="string">stable:no</data> + <data name="tag" xsi:type="string">severity:S3, stable:no</data> <data name="description" xsi:type="string">Verify sales credit memo grid full text search</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridSortingTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridSortingTest.xml index f82f232625841ddfdd77e66812970a4de31efea6..75d5c7fd09d95200255119b7b00c7167eb8c0142 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridSortingTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridSortingTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridSortingTest" summary="Grid UI Component Sorting" ticketId="MAGETWO-41328"> <variation name="SalesOrderGridSorting"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="description" xsi:type="string">Verify sales order grid storting</data> <data name="steps" xsi:type="array"> @@ -27,6 +28,7 @@ <constraint name="\Magento\Ui\Test\Constraint\AssertGridSorting"/> </variation> <variation name="SalesInvoiceGridSorting"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="description" xsi:type="string">Verify sales invoince grid storting</data> <data name="steps" xsi:type="array"> @@ -45,6 +47,7 @@ <constraint name="\Magento\Ui\Test\Constraint\AssertGridSorting"/> </variation> <variation name="SalesShipmentGridSorting"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="description" xsi:type="string">Verify sales shipment grid storting</data> <data name="steps" xsi:type="array"> @@ -63,6 +66,7 @@ <constraint name="\Magento\Ui\Test\Constraint\AssertGridSorting"/> </variation> <variation name="SalesCreditMemoGridSorting"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="description" xsi:type="string">Verify sales credit memo grid storting</data> <data name="steps" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/etc/di.xml index f42c97e1a6614a927da685f9cd5e1f8c84ff0c32..df10cccbd82136f027f4ee6b236cafe272cdbdc8 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/etc/di.xml @@ -11,6 +11,11 @@ <argument name="severity" xsi:type="string">S0</argument> </arguments> </type> + <type name="Magento\Sales\Test\Constraint\AssertInvoiceStatusInOrdersGrid"> + <arguments> + <argument name="severity" xsi:type="string">S1</argument> + </arguments> + </type> <type name="Magento\Sales\Test\Constraint\AssertOrderStatusDuplicateStatus"> <arguments> <argument name="severity" xsi:type="string">S0</argument> diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertCityBasedShippingRateChanged.php b/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertCityBasedShippingRateChanged.php new file mode 100644 index 0000000000000000000000000000000000000000..a10b47a2f9950f311d4c8ebcbdd3babb46faf6a8 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertCityBasedShippingRateChanged.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Shipping\Test\Constraint; + +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Check that Shipping rate changes due to City change. + */ +class AssertCityBasedShippingRateChanged extends AbstractConstraint +{ + /** + * Assert that Shipping rate changed on City change. + * + * @param CheckoutOnepage $checkoutOnepage + * @param array $shippingMethod + * @param bool $isShippingAvailable + * @return void + */ + public function processAssert(CheckoutOnepage $checkoutOnepage, $shippingMethod, $isShippingAvailable) + { + if ($isShippingAvailable) { + \PHPUnit_Framework_Assert::assertTrue( + $checkoutOnepage->getShippingMethodBlock()->isLoaderAppeared(), + 'Shipping rate has not been changed.' + ); + } + $shippingAvaialability = $isShippingAvailable ? 'avaiable' : 'unavailable'; + \PHPUnit_Framework_Assert::assertEquals( + $isShippingAvailable, + $checkoutOnepage->getShippingMethodBlock()->isShippingMethodAvaiable($shippingMethod), + "Shipping rates for {$shippingMethod['shipping_service']} should be $shippingAvaialability." + ); + } + + /** + * Returns a string representation of successful assertion. + * + * @return string + */ + public function toString() + { + return "Shipping rate has been changed."; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/TestCase/CityBasedShippingRateTest.php b/dev/tests/functional/tests/app/Magento/Shipping/Test/TestCase/CityBasedShippingRateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..294cf129c607308425fc6e9a3574b047d8b2ff18 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/TestCase/CityBasedShippingRateTest.php @@ -0,0 +1,44 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Shipping\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Preconditions: + * 1. Configure shipping method. + * 2. Create products. + * 3. Create and setup customer. + * + * Steps: + * 1. Go to Frontend. + * 2. Add products to the cart. + * 3. Click the 'Proceed to Checkout' button. + * 4. Fill shipping information. + * 5. Perform assertions. + * + * @group Shipping + * @ZephyrId MAGETWO-56124 + */ +class CityBasedShippingRateTest extends Scenario +{ + /* tags */ + const MVP = 'yes'; + const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S1'; + /* end tags */ + + /** + * Runs City Based Shipping Rate test. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/TestStep/FillShippingAddressesStep.php b/dev/tests/functional/tests/app/Magento/Shipping/Test/TestStep/FillShippingAddressesStep.php new file mode 100644 index 0000000000000000000000000000000000000000..8a0f5ea7e269d71234e3cdacbc8c570c6bb040ed --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/TestStep/FillShippingAddressesStep.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Shipping\Test\TestStep; + +use Magento\Mtf\Fixture\FixtureFactory; +use Magento\Mtf\TestStep\TestStepInterface; +use Magento\Customer\Test\Fixture\Address; +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Shipping\Test\Constraint\AssertCityBasedShippingRateChanged; + +/** + * Fill shipping addresses and assert rates relouding. + */ +class FillShippingAddressesStep implements TestStepInterface +{ + /** + * Onepage checkout page. + * + * @var CheckoutOnepage + */ + private $checkoutOnepage; + + /** + * Address fixture. + * + * @var Address[] + */ + private $shippingAddresses; + + /** + * Assert City based Shipping rate. + * + * @var array + */ + private $assertRate; + + /** + * @var array + */ + private $isShippingAvailable; + + /** + * Shipping method. + * + * @var array + */ + private $shippingMethod; + + /** + * @param CheckoutOnepage $checkoutOnepage + * @param FixtureFactory $fixtureFactory + * @param AssertCityBasedShippingRateChanged $assertRate + * @param array $shippingMethod + * @param array $shippingAddresses + * @param array $clearShippingAddress + * @param array $isShippingAvailable + */ + public function __construct( + CheckoutOnepage $checkoutOnepage, + FixtureFactory $fixtureFactory, + AssertCityBasedShippingRateChanged $assertRate, + array $shippingMethod, + array $shippingAddresses, + array $clearShippingAddress, + array $isShippingAvailable + ) { + $this->checkoutOnepage = $checkoutOnepage; + $this->assertRate = $assertRate; + + foreach ($shippingAddresses as $address) { + $data = array_merge($clearShippingAddress, $address); + $this->shippingAddresses[] = $fixtureFactory->createByCode('address', ['data' => $data]); + } + $this->isShippingAvailable = $isShippingAvailable; + $this->shippingMethod = $shippingMethod; + } + + /** + * Fill shipping address and assert if the shipping rates is reloaded. + * + * @return void + */ + public function run() + { + foreach ($this->shippingAddresses as $key => $shippingAddress) { + $this->checkoutOnepage->getShippingBlock()->fill($shippingAddress); + $this->assertRate->processAssert( + $this->checkoutOnepage, + $this->shippingMethod, + $this->isShippingAvailable[$key] + ); + } + } +} diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Shipping/Test/etc/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..d0d24b810fb44bd0caa7dec1e6b302006904b102 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/etc/di.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\Shipping\Test\Constraint\AssertCityBasedShippingRateChanged"> + <arguments> + <argument name="severity" xsi:type="string">S1</argument> + </arguments> + </type> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Shipping/Test/etc/testcase.xml new file mode 100644 index 0000000000000000000000000000000000000000..b1fabed80066b6933f58f89e69aa59ea20042d65 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/etc/testcase.xml @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/Magento/Mtf/TestCase/etc/testcase.xsd"> + <scenario name="CityBasedShippingRateTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> + <step name="createProducts" module="Magento_Catalog" next="addProductsToTheCart" /> + <step name="addProductsToTheCart" module="Magento_Checkout" next="proceedToCheckout" /> + <step name="proceedToCheckout" module="Magento_Checkout" next="createCustomer" /> + <step name="createCustomer" module="Magento_Customer" next="selectCheckoutMethod" /> + <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddresses" /> + <step name="fillShippingAddresses" module="Magento_Shipping" /> + </scenario> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFilteringTest.php b/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFilteringTest.php index 4b923dd4344a93be0e2bf3491c30eecf823f76ba..7a3da9b3fa7cd1d74bf0cc707f8b0be2ddc1214e 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFilteringTest.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFilteringTest.php @@ -28,6 +28,7 @@ use Magento\Ui\Test\Block\Adminhtml\DataGrid; class GridFilteringTest extends Injectable { /* tags */ + const SEVERITY = 'S2'; const STABLE = 'no'; const MVP = 'no'; /* end tags */ diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFullTextSearchTest.php b/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFullTextSearchTest.php index 510d2d61c0acd2100b295ee1422015b1833d9c36..a16d61e112a83a2b008f49d9b95e072aec06d7ec 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFullTextSearchTest.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFullTextSearchTest.php @@ -28,6 +28,7 @@ use Magento\Ui\Test\Block\Adminhtml\DataGrid; class GridFullTextSearchTest extends Injectable { /* tags */ + const SEVERITY = 'S2'; const STABLE = 'no'; const MVP = 'no'; /* end tags */ diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridSortingTest.php b/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridSortingTest.php index d1f543c7b989137c209bdbd63e6c4755644e9e8b..319ef215bcb142677d847a2c3e6ce0af6ba80199 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridSortingTest.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridSortingTest.php @@ -28,6 +28,7 @@ use Magento\Ui\Test\Block\Adminhtml\DataGrid; class GridSortingTest extends Injectable { /* tags */ + const SEVERITY = 'S2'; const MVP = 'no'; /* end tags */ diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Ui/Test/etc/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..8982c1966306252a5d0113ac49e8efdb011e8ddb --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/etc/di.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\Ui\Test\Constraint\AssertGridFiltering"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Ui\Test\Constraint\AssertGridFullTextSearch"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Ui\Test\Constraint\AssertGridSorting"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/CheckSaveCreditCardOptionStep.php b/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/CheckSaveCreditCardOptionStep.php index b0f33872103f27ffe00e2b1323574fa0fdc6b88a..eee0f1be86ef79198a7864df8be90e8a225ea840 100644 --- a/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/CheckSaveCreditCardOptionStep.php +++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/CheckSaveCreditCardOptionStep.php @@ -36,28 +36,28 @@ class CheckSaveCreditCardOptionStep implements TestStepInterface private $payment; /** - * If vault is enabled for payment method. + * If 'Save for later use' checkbox is present in credit card form. * * @var null|bool */ - private $isVaultEnabled; + private $isVaultPresent; /** * @param CheckoutOnepage $checkoutOnepage * @param AssertSaveCreditCardOptionNotPresent $assertSaveCreditCardOptionNotPresent * @param array $payment - * @param null|bool $isVaultEnabled + * @param null|bool $isVaultPresent */ public function __construct( CheckoutOnepage $checkoutOnepage, AssertSaveCreditCardOptionNotPresent $assertSaveCreditCardOptionNotPresent, array $payment, - $isVaultEnabled = null + $isVaultPresent = null ) { $this->checkoutOnepage = $checkoutOnepage; $this->assertSaveCreditCardOptionNotPresent = $assertSaveCreditCardOptionNotPresent; $this->payment = $payment; - $this->isVaultEnabled = $isVaultEnabled; + $this->isVaultPresent = $isVaultPresent; } /** @@ -67,7 +67,7 @@ class CheckSaveCreditCardOptionStep implements TestStepInterface */ public function run() { - if ($this->isVaultEnabled === false) { + if ($this->isVaultPresent === false) { $this->assertSaveCreditCardOptionNotPresent->processAssert( $this->checkoutOnepage, $this->payment['method'] diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Vault/Test/etc/testcase.xml index 6289a8392ee7544777959e8afffe9fd999388713..ee55d7ef5ba905973cbbfb38effab1ccc7f750e0 100644 --- a/dev/tests/functional/tests/app/Magento/Vault/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/Vault/Test/etc/testcase.xml @@ -56,7 +56,8 @@ <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress" /> <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" /> <step name="fillShippingMethod" module="Magento_Checkout" next="selectPaymentMethod" /> - <step name="selectPaymentMethod" module="Magento_Checkout" next="fillBillingInformation" /> + <step name="selectPaymentMethod" module="Magento_Checkout" next="checkSaveCreditCardOption" /> + <step name="checkSaveCreditCardOption" module="Magento_Vault" next="fillBillingInformation" /> <step name="fillBillingInformation" module="Magento_Checkout" next="placeOrder" /> <step name="placeOrder" module="Magento_Checkout" next="openOrder" /> <step name="openOrder" module="Magento_Sales" next="reorder" /> diff --git a/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetRecentlyComparedProducts.php b/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetRecentlyComparedProducts.php index 745c3afe0aa91cc794d99e7312b620128d3306b4..c32ba27b671655a47a8400391f5fc7a7671d7083 100644 --- a/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetRecentlyComparedProducts.php +++ b/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetRecentlyComparedProducts.php @@ -118,6 +118,7 @@ class AssertWidgetRecentlyComparedProducts extends AbstractConstraint protected function removeCompareProducts() { $this->cmsIndex->open(); + $this->cmsIndex->getCompareLinkBlock()->waitForCompareProductsLinks(); $this->cmsIndex->getLinksBlock()->openLink("Compare Products"); $this->catalogProductCompare->getCompareProductsBlock()->removeAllProducts(); } diff --git a/dev/tests/functional/tests/app/Magento/Widget/Test/TestCase/CreateWidgetEntityTest.xml b/dev/tests/functional/tests/app/Magento/Widget/Test/TestCase/CreateWidgetEntityTest.xml index 225759df91f179dbd911fca662c05476c4830a69..57920ead79a7d113e37123d3603462759728393c 100644 --- a/dev/tests/functional/tests/app/Magento/Widget/Test/TestCase/CreateWidgetEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Widget/Test/TestCase/CreateWidgetEntityTest.xml @@ -42,7 +42,7 @@ <constraint name="Magento\Widget\Test\Constraint\AssertWidgetRecentlyViewedProducts" /> </variation> <variation name="CreateWidgetEntityTestVariation4"> - <data name="tag" xsi:type="string">severity:S1, stable:no</data> + <data name="tag" xsi:type="string">severity:S1</data> <data name="widget/data/code" xsi:type="string">Recently Compared Products</data> <data name="widget/data/theme_id" xsi:type="string">Magento Luma</data> <data name="widget/data/title" xsi:type="string">Title_%isolation%</data> diff --git a/dev/tests/integration/testsuite/Magento/Authorizenet/Model/Directpost/RequestTest.php b/dev/tests/integration/testsuite/Magento/Authorizenet/Model/Directpost/RequestTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ab35c27985da8f13fb2fd4362c719fe0d3267315 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Authorizenet/Model/Directpost/RequestTest.php @@ -0,0 +1,102 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Authorizenet\Model\Directpost; + +use Magento\Authorizenet\Model\Directpost; +use Magento\Framework\Api\FilterBuilder; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\App\ObjectManager; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit_Framework_MockObject_MockObject as MockObject; + +/** + * Class contains tests for Authorize.net Direct Post request handler + */ +class RequestTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Order + */ + private $order; + + /** + * @var Request + */ + private $request; + + /** + * @var ObjectManager + */ + private $objectManager; + + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + + $this->order = $this->getOrder(); + $this->request = $this->objectManager->get(Request::class); + } + + /** + * @covers \Magento\Authorizenet\Model\Directpost\Request::setDataFromOrder + * @magentoDataFixture Magento/Authorizenet/_files/order.php + */ + public function testSetDataFromOrder() + { + $customerEmail = 'john.doe@example.com'; + $merchantEmail = 'merchant@example.com'; + + /** @var Directpost|MockObject $payment */ + $payment = $this->getMockBuilder(Directpost::class) + ->disableOriginalConstructor() + ->setMethods(['getConfigData']) + ->getMock(); + + $payment->expects(static::exactly(2)) + ->method('getConfigData') + ->willReturnMap([ + ['email_customer', null, $customerEmail], + ['merchant_email', null, $merchantEmail] + ]); + + $result = $this->request->setDataFromOrder($this->order, $payment); + + static::assertEquals('US', $result->getXCountry()); + static::assertEquals('UK', $result->getXShipToCountry()); + static::assertEquals($customerEmail, $result->getXEmailCustomer()); + static::assertEquals($merchantEmail, $result->getXMerchantEmail()); + } + + /** + * Get stored order + * @return Order + */ + private function getOrder() + { + /** @var FilterBuilder $filterBuilder */ + $filterBuilder = $this->objectManager->get(FilterBuilder::class); + $filters = [ + $filterBuilder->setField(OrderInterface::INCREMENT_ID) + ->setValue('100000002') + ->create() + ]; + + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchCriteriaBuilder->addFilters($filters) + ->create(); + + $orderRepository = $this->objectManager->get(OrderRepositoryInterface::class); + $orders = $orderRepository->getList($searchCriteria) + ->getItems(); + + /** @var OrderInterface $order */ + return array_pop($orders); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Authorizenet/Model/DirectpostTest.php b/dev/tests/integration/testsuite/Magento/Authorizenet/Model/DirectpostTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c20db43c127b4a9c058cb206cde14822f9aafd84 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Authorizenet/Model/DirectpostTest.php @@ -0,0 +1,129 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Authorizenet\Model; + +use Magento\Framework\Api\FilterBuilder; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\HTTP\ZendClient; +use Magento\Framework\HTTP\ZendClientFactory; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order\Payment; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit_Framework_MockObject_MockObject as MockObject; +use Zend_Http_Response; + +/** + * Class contains tests for Direct Post integration + */ +class DirectpostTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var ZendClientFactory|MockObject + */ + private $httpClientFactory; + + /** + * @var Directpost + */ + private $directPost; + + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + + $this->httpClientFactory = $this->getMockBuilder(ZendClientFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->directPost = $this->objectManager->create(Directpost::class, [ + 'httpClientFactory' => $this->httpClientFactory + ]); + } + + /** + * @covers \Magento\Authorizenet\Model\Directpost::capture + * @magentoDataFixture Magento/Authorizenet/_files/order.php + */ + public function testCapture() + { + $amount = 120.15; + /** @var Payment $payment */ + $payment = $this->getPayment(); + $transactionId = '106235225'; + + /** @var ZendClient|MockObject $httpClient */ + $httpClient = $this->getMockBuilder(ZendClient::class) + ->disableOriginalConstructor() + ->setMethods(['setUri', 'setConfig', 'setParameterPost', 'setMethod', 'request']) + ->getMock(); + + $this->httpClientFactory->expects(static::once()) + ->method('create') + ->willReturn($httpClient); + + $response = $this->getMockBuilder(Zend_Http_Response::class) + ->disableOriginalConstructor() + ->setMethods(['getBody']) + ->getMock(); + $response->expects(static::once()) + ->method('getBody') + ->willReturn( + "1(~)1(~)1(~)This transaction has been approved.(~)AWZFTG(~)P(~){$transactionId}(~)100000002(~) + (~)120.15(~)CC(~)prior_auth_capture(~)(~)Anthony(~)Nealy(~)(~)Pearl St(~)Los Angeles(~)California + (~)10020(~)US(~)22-333-44(~)(~)customer@example.com(~)John(~)Doe(~) + (~)Bourne St(~)London(~)(~)DW23W(~)UK(~)0.00(~)(~){$amount}(~)(~) + (~)74B5D54ADFE98093A0FF6446(~)(~)(~)(~)(~)(~)(~)(~)(~)(~)(~)(~)(~)XXXX1111(~)Visa(~)(~)(~)(~)(~) + (~)(~)(~)(~)(~)(~)(~)(~)(~)(~)(~)(~)" + ); + + $httpClient->expects(static::once()) + ->method('request') + ->willReturn($response); + + $this->directPost->capture($payment, $amount); + + static::assertEquals($transactionId, $payment->getTransactionId()); + static::assertFalse($payment->getIsTransactionClosed()); + static::assertEquals('US', $payment->getOrder()->getBillingAddress()->getCountryId()); + static::assertEquals('UK', $payment->getOrder()->getShippingAddress()->getCountryId()); + } + + /** + * Get order payment + * @return Payment + */ + private function getPayment() + { + /** @var FilterBuilder $filterBuilder */ + $filterBuilder = $this->objectManager->get(FilterBuilder::class); + $filters = [ + $filterBuilder->setField(OrderInterface::INCREMENT_ID) + ->setValue('100000002') + ->create() + ]; + + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchCriteriaBuilder->addFilters($filters) + ->create(); + + $orderRepository = $this->objectManager->get(OrderRepositoryInterface::class); + $orders = $orderRepository->getList($searchCriteria) + ->getItems(); + + /** @var OrderInterface $order */ + $order = array_pop($orders); + return $order->getPayment(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Authorizenet/_files/order.php b/dev/tests/integration/testsuite/Magento/Authorizenet/_files/order.php new file mode 100644 index 0000000000000000000000000000000000000000..564ab84a8f8527c61bf8e79f7a57ad53b971089f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Authorizenet/_files/order.php @@ -0,0 +1,70 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Address; +use Magento\Sales\Model\Order\Payment; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); + +$amount = 120.15; + +/** @var Payment $payment */ +$payment = $objectManager->get(Payment::class); +$payment + ->setMethod('authorizenet_directpost') + ->setAnetTransType('AUTH_ONLY') + ->setBaseAmountAuthorized($amount) + ->setPoNumber('10101200'); + +/** @var Address\ $billingAddress */ +$billingAddress = $objectManager->create(Address::class, [ + 'data' => [ + 'firstname' => 'John', + 'lastname' => 'Doe', + 'email' => 'customer@example.com', + 'street' => 'Pearl St', + 'city' => 'Los Angeles', + 'region' => 'CA', + 'postcode' => '10020', + 'country_id' => 'US', + 'telephone' => '22-333-44', + 'address_type' => 'billing' + ] +]); + +$shippingAddress = $objectManager->create(Address::class, [ + 'data' => [ + 'firstname' => 'John', + 'lastname' => 'Doe', + 'email' => 'customer@example.com', + 'street' => 'Bourne St', + 'city' => 'London', + 'postcode' => 'DW23W', + 'country_id' => 'UK', + 'telephone' => '22-333-44', + 'address_type' => 'billing' + ] +]); + +/** @var Order $order */ +$order = $objectManager->create(Order::class); +$order->setIncrementId('100000002') + ->setQuoteId(2) + ->setIncrementId('100000002') + ->setBaseGrandTotal($amount) + ->setBaseCurrencyCode('USD') + ->setBaseTaxAmount($amount) + ->setBaseShippingAmount($amount) + ->setCustomerEmail('customer@example.com') + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setPayment($payment); + +/** @var OrderRepositoryInterface $orderRepository */ +$orderRepository = $objectManager->get(OrderRepositoryInterface::class); +$orderRepository->save($order); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/ProcessorTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/ProcessorTest.php index 9c9e564939070e99b097477a221f445811a25ef1..ae954fdc7cfbb7bdc7c66dfb4ab9a25e977e8fae 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/ProcessorTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/ProcessorTest.php @@ -146,15 +146,15 @@ class ProcessorTest extends \PHPUnit_Framework_TestCase ); $product->setData(['image' => 'test1', 'small_image' => 'test2', 'thumbnail' => 'test3']); - $this->assertNotEmpty($product->getData('image')); + $this->assertNotEquals('no_selection', $product->getData('image')); $this->_model->clearMediaAttribute($product, 'image'); - $this->assertNull($product->getData('image')); + $this->assertEquals('no_selection', $product->getData('image')); - $this->assertNotEmpty($product->getData('small_image')); - $this->assertNotEmpty($product->getData('thumbnail')); + $this->assertNotEquals('no_selection', $product->getData('small_image')); + $this->assertNotEquals('no_selection', $product->getData('thumbnail')); $this->_model->clearMediaAttribute($product, ['small_image', 'thumbnail']); - $this->assertNull($product->getData('small_image')); - $this->assertNull($product->getData('thumbnail')); + $this->assertEquals('no_selection', $product->getData('small_image')); + $this->assertEquals('no_selection', $product->getData('thumbnail')); } public function testSetMediaAttribute() diff --git a/dev/tests/integration/testsuite/Magento/Directory/Model/ObserverTest.php b/dev/tests/integration/testsuite/Magento/Directory/Model/ObserverTest.php index 389fd4b253eb7c8e8a89237f1b7a20be9aa777fe..95fd6110bb432e72daa2af66d7b65f7abbdb3d0f 100644 --- a/dev/tests/integration/testsuite/Magento/Directory/Model/ObserverTest.php +++ b/dev/tests/integration/testsuite/Magento/Directory/Model/ObserverTest.php @@ -62,12 +62,12 @@ class ObserverTest extends \PHPUnit_Framework_TestCase { //skipping test if service is unavailable $url = str_replace('{{CURRENCY_FROM}}', 'USD', - \Magento\Directory\Model\Currency\Import\Webservicex::CURRENCY_CONVERTER_URL + \Magento\Directory\Model\Currency\Import\Webservicex::CURRENCY_CONVERTER_URL ); $url = str_replace('{{CURRENCY_TO}}', 'GBP', $url); try { file_get_contents($url); - } catch (\PHPUnit_Framework_Error_Warning $e) { + } catch (\PHPUnit_Framework_Exception $e) { $this->markTestSkipped('http://www.webservicex.net is unavailable '); } diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php index 383cc31a84228631d62864e9e2f6c2d78551d9d5..41b0fdaff08c5b0b8b7291347a2a121cf0a4c68b 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php @@ -125,6 +125,7 @@ class SubtotalTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expected['subtotal'], $total->getSubtotal()); $this->assertEquals($expected['subtotal'] + $expected['tax_amount'], $total->getSubtotalInclTax()); + $this->assertEquals($expected['subtotal'] + $expected['tax_amount'], $address->getBaseSubtotalTotalInclTax()); $this->assertEquals($expected['discount_amount'], $total->getDiscountAmount()); $items = $address->getAllItems(); /** @var \Magento\Quote\Model\Quote\Address\Item $item */ diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js index db5855b0a692bb7ac0c9b75de35d228abe309016..5d75b8c595366169166d3964bbd95d988b1d5606 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js @@ -121,7 +121,7 @@ define([ { value: 'valLast' }]; - model.caption = false; + model.caption(''); expect(model.normalizeData('')).toEqual('valFirst'); }); }); diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/ApiAnnotationTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/ApiAnnotationTest.php deleted file mode 100644 index a1e7c25e3d6008cff744a090c0c01a810efad8a4..0000000000000000000000000000000000000000 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/ApiAnnotationTest.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php -/** - * Scan source code for unmarked API interfaces - * - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Test\Integrity; - -use Magento\Framework\App\Utility\Files; -use Magento\Framework\Component\ComponentRegistrar; - -class ApiAnnotationTest extends \PHPUnit_Framework_TestCase -{ - /** - * API annotation pattern - */ - private $apiAnnotation = '~/\*{2}(.*@api.*)\*/\s+(?=interface)~s'; - - public function testApiAnnotations() - { - $modulePaths = array_map(function ($path) { - return $path . DIRECTORY_SEPARATOR . 'Api'; - }, (new ComponentRegistrar())->getPaths(ComponentRegistrar::MODULE)); - - foreach (Files::init()->getFiles($modulePaths, '*.php', true) as $file) { - $fileContent = file_get_contents($file); - if (!preg_match($this->apiAnnotation, $fileContent)) { - $result[] = $file; - } - } - if (!empty($result)) { - $this->fail(sprintf( - 'Found %s file(s) without @api annotations under Api namespace: %s', - count($result), - PHP_EOL . implode(PHP_EOL, $result) - )); - } - } -} diff --git a/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Checksum.php b/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Checksum.php index bfdd516de7e366a3df4773776abec8e118b3916f..44b5bb65c49d36f690490e130f68c3868f162ce6 100644 --- a/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Checksum.php +++ b/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Checksum.php @@ -6,6 +6,8 @@ namespace Magento\Framework\View\Asset\MergeStrategy; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\View\Asset\Source; /** * Skip merging if all of the files that need to be merged were not modified @@ -25,6 +27,11 @@ class Checksum implements \Magento\Framework\View\Asset\MergeStrategyInterface */ protected $filesystem; + /** + * @var Source + */ + private $assetSource; + /** * @param \Magento\Framework\View\Asset\MergeStrategyInterface $strategy * @param \Magento\Framework\Filesystem $filesystem @@ -37,17 +44,31 @@ class Checksum implements \Magento\Framework\View\Asset\MergeStrategyInterface $this->filesystem = $filesystem; } + /** + * @deprecated + * @return Source + */ + private function getAssetSource() + { + if (!$this->assetSource) { + $this->assetSource = ObjectManager::getInstance()->get(Source::class); + } + return $this->assetSource; + } + /** * {@inheritdoc} */ public function merge(array $assetsToMerge, \Magento\Framework\View\Asset\LocalInterface $resultAsset) { - $sourceDir = $this->filesystem->getDirectoryRead(DirectoryList::ROOT); + $rootDir = $this->filesystem->getDirectoryRead(DirectoryList::ROOT); $mTime = null; /** @var \Magento\Framework\View\Asset\MergeableInterface $asset */ foreach ($assetsToMerge as $asset) { - $mTime .= $sourceDir->stat($sourceDir->getRelativePath($asset->getSourceFile()))['mtime']; + $sourceFile = $this->getAssetSource()->findSource($asset); + $mTime .= $rootDir->stat($rootDir->getRelativePath($sourceFile))['mtime']; } + if (null === $mTime) { return; // nothing to merge } diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php index 9c7859116c4cbcc3da0947e6a39e5f1295dc4a8b..b20420640ebe42b31472299b2879f2f13f6abbe1 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php @@ -8,6 +8,7 @@ namespace Magento\Framework\View\Test\Unit\Asset\MergeStrategy; use \Magento\Framework\View\Asset\MergeStrategy\Checksum; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\View\Asset\Source; class ChecksumTest extends \PHPUnit_Framework_TestCase { @@ -31,6 +32,11 @@ class ChecksumTest extends \PHPUnit_Framework_TestCase */ private $resultAsset; + /** + * @var Source|\PHPUnit_Framework_MockObject_MockObject + */ + private $assetSource; + /** * @var \Magento\Framework\View\Asset\MergeStrategy\Checksum */ @@ -53,6 +59,15 @@ class ChecksumTest extends \PHPUnit_Framework_TestCase ->with(DirectoryList::STATIC_VIEW) ->will($this->returnValue($this->targetDir)); $this->checksum = new Checksum($this->mergerMock, $filesystem); + $this->assetSource = $this->getMockBuilder(Source::class) + ->disableOriginalConstructor() + ->getMock(); + + $reflection = new \ReflectionClass(Checksum::class); + $reflectionProperty = $reflection->getProperty('assetSource'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->checksum, $this->assetSource); + $this->resultAsset = $this->getMock(\Magento\Framework\View\Asset\File::class, [], [], '', false); } @@ -114,9 +129,17 @@ class ChecksumTest extends \PHPUnit_Framework_TestCase private function getAssetsToMerge() { $one = $this->getMock(\Magento\Framework\View\Asset\File::class, [], [], '', false); - $one->expects($this->once())->method('getSourceFile')->will($this->returnValue('/dir/file/one.txt')); $two = $this->getMock(\Magento\Framework\View\Asset\File::class, [], [], '', false); - $two->expects($this->once())->method('getSourceFile')->will($this->returnValue('/dir/file/two.txt')); + $one->expects($this->never()) + ->method('getSourceFile'); + $two->expects($this->never()) + ->method('getSourceFile'); + + $this->assetSource->expects($this->exactly(2)) + ->method('findSource') + ->withConsecutive([$one], [$two]) + ->willReturnOnConsecutiveCalls('/dir/file/one.txt', '/dir/file/two.txt'); + $this->sourceDir->expects($this->exactly(2)) ->method('getRelativePath') ->will($this->onConsecutiveCalls('file/one.txt', 'file/two.txt'));