From edf5ffb8e2988f23c524bb2e989b7d696d189ab8 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 4 Nov 2016 06:50:18 -0400 Subject: [PATCH 01/10] MAGETWO-56695: Paypal checkout not possible with products that have custom options #5938 - for 2.1 --- app/code/Magento/Catalog/Model/Product.php | 11 +++++---- .../Catalog/Test/Unit/Model/ProductTest.php | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index 29082eb83849c..6c15997329918 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -1905,13 +1905,14 @@ public function addOption(Product\Option $option) */ public function getOptionById($optionId) { - /** @var \Magento\Catalog\Model\Product\Option $option */ - foreach ($this->getOptions() as $option) { - if ($option->getId() == $optionId) { - return $option; + if (is_array($this->getOptions())) { + /** @var \Magento\Catalog\Model\Product\Option $option */ + foreach ($this->getOptions() as $option) { + if ($option->getId() == $optionId) { + return $option; + } } } - return null; } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php index ad637d347fc40..0b6fcc10b9542 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php @@ -1332,4 +1332,27 @@ public function testGetTypeId() $this->model->setTypeId('typeId'); $this->model->getTypeInstance(); } + + public function testGetOptionById() + { + $optionId = 100; + $optionMock = $this->getMock(\Magento\Catalog\Model\Product\Option::class, [], [], '', false); + $this->model->setOptions([$optionMock]); + $optionMock->expects($this->once())->method('getId')->willReturn($optionId); + $this->assertEquals($optionMock, $this->model->getOptionById($optionId)); + } + + public function testGetOptionByIdWithWrongOptionId() + { + $optionId = 100; + $optionMock = $this->getMock(\Magento\Catalog\Model\Product\Option::class, [], [], '', false); + $this->model->setOptions([$optionMock]); + $optionMock->expects($this->once())->method('getId')->willReturn(200); + $this->assertNull($this->model->getOptionById($optionId)); + } + + public function testGetOptionByIdForProductWithoutOptions() + { + $this->assertNull($this->model->getOptionById(100)); + } } From d8be7ede72db5d98695fe9ee3826e79108cf105e Mon Sep 17 00:00:00 2001 From: RomaKis Date: Sat, 5 Nov 2016 12:14:12 +0200 Subject: [PATCH 02/10] MAGETWO-58893: [Backport] [GitHub] IndexerHandlerFactory: Indexer Object cast to String - 2.1 --- .../Model/Indexer/IndexerHandlerFactory.php | 7 +- .../Indexer/IndexerHandlerFactoryTest.php | 173 ++++++++++++++++++ 2 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/IndexerHandlerFactoryTest.php diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandlerFactory.php b/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandlerFactory.php index bb2df11c9083d..d0e9cd7693e79 100644 --- a/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandlerFactory.php +++ b/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandlerFactory.php @@ -75,14 +75,17 @@ public function create(array $data = []) $indexer = $this->_objectManager->create($this->handlers[$currentHandler], $data); if (!$indexer instanceof IndexerInterface) { - throw new \InvalidArgumentException($indexer . ' doesn\'t implement \Magento\Framework\IndexerInterface'); + throw new \InvalidArgumentException( + $currentHandler . ' indexer handler doesn\'t implement ' . IndexerInterface::class + ); } if ($indexer && !$indexer->isAvailable()) { throw new \LogicException( - 'Indexer handler is not available: ' . $indexer + 'Indexer handler is not available: ' . $currentHandler ); } + return $indexer; } } diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/IndexerHandlerFactoryTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/IndexerHandlerFactoryTest.php new file mode 100644 index 0000000000000..417eb63d08ab4 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/IndexerHandlerFactoryTest.php @@ -0,0 +1,173 @@ +objectManagerMock = $this->getMockBuilder(ObjectManagerInterface::class) + ->getMockForAbstractClass(); + $this->scopeConfigMock = $this->getMockBuilder(ScopeConfigInterface::class) + ->getMockForAbstractClass(); + } + + public function testCreate() + { + $configPath = 'config_path'; + $currentHandler = 'current_handler'; + $currentHandlerClass = 'current_handler_class'; + $handlers = [ + $currentHandler => $currentHandlerClass, + ]; + $data = ['data']; + + $this->scopeConfigMock->expects($this->once()) + ->method('getValue') + ->with($configPath, ScopeInterface::SCOPE_STORE) + ->willReturn($currentHandler); + + $indexerMock = $this->getMockBuilder(IndexerInterface::class) + ->getMockForAbstractClass(); + + $this->objectManagerMock->expects($this->once()) + ->method('create') + ->with($currentHandlerClass, $data) + ->willReturn($indexerMock); + + $indexerMock->expects($this->once()) + ->method('isAvailable') + ->willReturn(true); + + $this->model = new IndexerHandlerFactory( + $this->objectManagerMock, + $this->scopeConfigMock, + $configPath, + $handlers + ); + + $this->assertEquals($indexerMock, $this->model->create($data)); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage There is no such indexer handler: current_handler + */ + public function testCreateWithoutHandlers() + { + $configPath = 'config_path'; + $currentHandler = 'current_handler'; + $handlers = []; + $data = ['data']; + + $this->scopeConfigMock->expects($this->once()) + ->method('getValue') + ->with($configPath, ScopeInterface::SCOPE_STORE) + ->willReturn($currentHandler); + + $this->model = new IndexerHandlerFactory( + $this->objectManagerMock, + $this->scopeConfigMock, + $configPath, + $handlers + ); + + $this->model->create($data); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage current_handler indexer handler doesn't implement + */ + public function testCreateWithWrongHandler() + { + $configPath = 'config_path'; + $currentHandler = 'current_handler'; + $currentHandlerClass = 'current_handler_class'; + $handlers = [ + $currentHandler => $currentHandlerClass, + ]; + $data = ['data']; + + $this->scopeConfigMock->expects($this->once()) + ->method('getValue') + ->with($configPath, ScopeInterface::SCOPE_STORE) + ->willReturn($currentHandler); + + $indexerMock = $this->getMockBuilder(\stdClass::class) + ->getMockForAbstractClass(); + + $this->objectManagerMock->expects($this->once()) + ->method('create') + ->with($currentHandlerClass, $data) + ->willReturn($indexerMock); + + $this->model = new IndexerHandlerFactory( + $this->objectManagerMock, + $this->scopeConfigMock, + $configPath, + $handlers + ); + + $this->model->create($data); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Indexer handler is not available: current_handler + */ + public function testCreateWithoutAvailableHandler() + { + $configPath = 'config_path'; + $currentHandler = 'current_handler'; + $currentHandlerClass = 'current_handler_class'; + $handlers = [ + $currentHandler => $currentHandlerClass, + ]; + $data = ['data']; + + $this->scopeConfigMock->expects($this->once()) + ->method('getValue') + ->with($configPath, ScopeInterface::SCOPE_STORE) + ->willReturn($currentHandler); + + $indexerMock = $this->getMockBuilder(IndexerInterface::class) + ->getMockForAbstractClass(); + + $this->objectManagerMock->expects($this->once()) + ->method('create') + ->with($currentHandlerClass, $data) + ->willReturn($indexerMock); + + $indexerMock->expects($this->once()) + ->method('isAvailable') + ->willReturn(false); + + $this->model = new IndexerHandlerFactory( + $this->objectManagerMock, + $this->scopeConfigMock, + $configPath, + $handlers + ); + + $this->model->create($data); + } +} From 1c7f70d751f3cb2bcd2e076e97b900a3fc3912cc Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 7 Nov 2016 04:05:23 -0500 Subject: [PATCH 03/10] MAGETWO-58376: PayPal Payflow Pro always using USD (even if this currency is absent on your store) - for 2.1 --- app/code/Magento/Paypal/Model/Payflow/Transparent.php | 1 + .../Paypal/Test/Unit/Model/Payflow/TransparentTest.php | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Paypal/Model/Payflow/Transparent.php b/app/code/Magento/Paypal/Model/Payflow/Transparent.php index 05609ee5ee88f..78bd063117400 100644 --- a/app/code/Magento/Paypal/Model/Payflow/Transparent.php +++ b/app/code/Magento/Paypal/Model/Payflow/Transparent.php @@ -167,6 +167,7 @@ public function authorize(InfoInterface $payment, $amount) $request->setData('trxtype', self::TRXTYPE_AUTH_ONLY); $request->setData('origid', $token); $request->setData('amt', $this->formatPrice($amount)); + $request->setData('currency', $order->getBaseCurrencyCode()); $response = $this->postRequest($request, $this->getConfig()); $this->processErrors($response); diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/TransparentTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/TransparentTest.php index bbbb3ea187d18..aa90173d7d21f 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/TransparentTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/TransparentTest.php @@ -122,7 +122,7 @@ protected function initializationAuthorizeMock() $this->orderMock = $this->getMockBuilder('Magento\Sales\Model\Order') ->setMethods([ 'getCustomerId', 'getBillingAddress', 'getShippingAddress', 'getCustomerEmail', - 'getId', 'getIncrementId' + 'getId', 'getIncrementId', 'getBaseCurrencyCode' ]) ->disableOriginalConstructor() ->getMock(); @@ -164,6 +164,9 @@ protected function buildRequestData() $this->paymentMock->expects($this->once()) ->method('getOrder') ->willReturn($this->orderMock); + $this->orderMock->expects($this->once()) + ->method('getBaseCurrencyCode') + ->willReturn('USD'); $this->orderMock->expects($this->once()) ->method('getBillingAddress') ->willReturn($this->addressBillingMock); From e2ebb8291e3a8a6df120662a3f1debc01595fff2 Mon Sep 17 00:00:00 2001 From: RomaKis Date: Mon, 7 Nov 2016 11:20:59 +0200 Subject: [PATCH 04/10] MAGETWO-59036: [Backport] [GITHUB] Broken File Type Custom Option #5434 - 2.1 --- .../Model/Product/Option/Type/File.php | 17 +++++-- .../Model/Product/Option/Type/FileTest.php | 47 +++++++++++++------ app/code/Magento/Catalog/etc/di.xml | 3 ++ app/code/Magento/Catalog/etc/frontend/di.xml | 3 -- 4 files changed, 49 insertions(+), 21 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/File.php b/app/code/Magento/Catalog/Model/Product/Option/Type/File.php index d974174ef7088..ed7195f1a2adc 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/File.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/File.php @@ -5,6 +5,7 @@ */ namespace Magento\Catalog\Model\Product\Option\Type; +use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem; use Magento\Framework\Exception\LocalizedException; use Magento\Catalog\Model\Product\Exception as ProductException; @@ -69,17 +70,22 @@ class File extends \Magento\Catalog\Model\Product\Option\Type\DefaultType */ protected $validatorFile; + /** + * @var Filesystem + */ + private $filesystem; + /** * @param \Magento\Checkout\Model\Session $checkoutSession * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Quote\Model\Quote\Item\OptionFactory $itemOptionFactory - * @param \Magento\Catalog\Model\Product\Option\UrlBuilder $urlBuilder - * @param \Magento\Framework\Escaper $escaper * @param \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDatabase * @param File\ValidatorInfo $validatorInfo * @param File\ValidatorFile $validatorFile + * @param \Magento\Catalog\Model\Product\Option\UrlBuilder $urlBuilder + * @param \Magento\Framework\Escaper $escaper * @param array $data - * @throws \Magento\Framework\Exception\FileSystemException + * @param Filesystem $filesystem */ public function __construct( \Magento\Checkout\Model\Session $checkoutSession, @@ -90,12 +96,15 @@ public function __construct( \Magento\Catalog\Model\Product\Option\Type\File\ValidatorFile $validatorFile, \Magento\Catalog\Model\Product\Option\UrlBuilder $urlBuilder, \Magento\Framework\Escaper $escaper, - array $data = [] + array $data = [], + Filesystem $filesystem = null ) { $this->_itemOptionFactory = $itemOptionFactory; $this->_urlBuilder = $urlBuilder; $this->_escaper = $escaper; $this->_coreFileStorageDatabase = $coreFileStorageDatabase; + $this->filesystem = $filesystem ?: \Magento\Framework\App\ObjectManager::getInstance()->get(Filesystem::class); + $this->_rootDirectory = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA); $this->validatorInfo = $validatorInfo; $this->validatorFile = $validatorFile; parent::__construct($checkoutSession, $scopeConfig, $data); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/Type/FileTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/Type/FileTest.php index 7a385fd1fc172..6682b29547632 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/Type/FileTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/Type/FileTest.php @@ -5,6 +5,12 @@ */ namespace Magento\Catalog\Test\Unit\Model\Product\Option\Type; +use Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface; +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Filesystem; +use Magento\Framework\Filesystem\Directory\ReadInterface; +use Magento\Framework\Filesystem\DriverPool; + class FileTest extends \PHPUnit_Framework_TestCase { /** @@ -13,7 +19,7 @@ class FileTest extends \PHPUnit_Framework_TestCase protected $objectManager; /** - * @var \Magento\Framework\Filesystem\Directory\ReadInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ReadInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $rootDirectory; @@ -22,17 +28,29 @@ class FileTest extends \PHPUnit_Framework_TestCase */ protected $coreFileStorageDatabase; + /** + * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject + */ + private $filesystemMock; + protected function setUp() { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->rootDirectory = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\ReadInterface') + $this->filesystemMock = $this->getMockBuilder(Filesystem::class) ->disableOriginalConstructor() - ->setMethods(['isFile', 'isReadable', 'getAbsolutePath']) - ->getMockForAbstractClass(); + ->getMock(); + + $this->rootDirectory = $this->getMockBuilder(ReadInterface::class) + ->getMock(); + + $this->filesystemMock->expects($this->once()) + ->method('getDirectoryRead') + ->with(DirectoryList::MEDIA, DriverPool::FILE) + ->willReturn($this->rootDirectory); $this->coreFileStorageDatabase = $this->getMock( - 'Magento\MediaStorage\Helper\File\Storage\Database', + \Magento\MediaStorage\Helper\File\Storage\Database::class, ['copyFile'], [], '', @@ -46,28 +64,29 @@ protected function setUp() protected function getFileObject() { return $this->objectManager->getObject( - 'Magento\Catalog\Model\Product\Option\Type\File', + \Magento\Catalog\Model\Product\Option\Type\File::class, [ - 'saleableItem' => $this->rootDirectory, - 'priceCurrency' => $this->coreFileStorageDatabase + 'filesystem' => $this->filesystemMock, + 'coreFileStorageDatabase' => $this->coreFileStorageDatabase ] ); } public function testCopyQuoteToOrder() { - $optionMock = $this->getMockBuilder( - 'Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface' - )->disableOriginalConstructor()->setMethods(['getValue'])->getMockForAbstractClass(); + $optionMock = $this->getMockBuilder(OptionInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getValue']) + ->getMockForAbstractClass(); $quotePath = '/quote/path/path/uploaded.file'; $orderPath = '/order/path/path/uploaded.file'; $optionMock->expects($this->any()) ->method('getValue') - ->will($this->returnValue(['quote_path' => $quotePath, 'order_path' => $orderPath])); + ->will($this->returnValue(serialize(['quote_path' => $quotePath, 'order_path' => $orderPath]))); - $this->rootDirectory->expects($this->any()) + $this->rootDirectory->expects($this->once()) ->method('isFile') ->with($this->equalTo($quotePath)) ->will($this->returnValue(true)); @@ -89,7 +108,7 @@ public function testCopyQuoteToOrder() $fileObject->setData('configuration_item_option', $optionMock); $this->assertInstanceOf( - 'Magento\Catalog\Model\Product\Option\Type\File', + \Magento\Catalog\Model\Product\Option\Type\File::class, $fileObject->copyQuoteToOrder() ); } diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index 89d9bf7734f2e..150d3ea048caf 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -800,4 +800,7 @@ + + + diff --git a/app/code/Magento/Catalog/etc/frontend/di.xml b/app/code/Magento/Catalog/etc/frontend/di.xml index 9b99bd4a78140..ac8c3693e8f30 100644 --- a/app/code/Magento/Catalog/etc/frontend/di.xml +++ b/app/code/Magento/Catalog/etc/frontend/di.xml @@ -18,9 +18,6 @@ Magento\Catalog\Model\ResourceModel\Category\Collection\FetchStrategy - - - true From 4d315019815f067c1e7c0f91361db5c28016a39e Mon Sep 17 00:00:00 2001 From: Myroslav Dobra Date: Mon, 7 Nov 2016 13:59:58 +0200 Subject: [PATCH 05/10] MAGETWO-58832: [Backport] Order comments history shows time of comment twice - for 2.1.x --- .../Adminhtml/Order/View/Tab/History.php | 8 +-- .../Adminhtml/Order/View/Tab/HistoryTest.php | 62 ++++++++++++++++++- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/History.php b/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/History.php index 8a6674aa154b0..51fb11927dbb2 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/History.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/History.php @@ -157,13 +157,11 @@ public function getItemCreatedAt(array $item, $dateType = 'date', $format = \Int if (!isset($item['created_at'])) { return ''; } - $date = $item['created_at'] instanceof \DateTimeInterface - ? $item['created_at'] - : new \DateTime($item['created_at']); if ('date' === $dateType) { - return $this->_localeDate->formatDateTime($date, $format, $format); + return $this->formatDate($item['created_at'], $format); } - return $this->_localeDate->formatDateTime($date, \IntlDateFormatter::NONE, $format); + + return $this->formatTime($item['created_at'], $format); } /** diff --git a/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/View/Tab/HistoryTest.php b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/View/Tab/HistoryTest.php index 79b349feabd88..1f8edb11e4f5f 100644 --- a/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/View/Tab/HistoryTest.php +++ b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/View/Tab/HistoryTest.php @@ -30,6 +30,17 @@ class HistoryTest extends \PHPUnit_Framework_TestCase */ protected $coreRegistryMock; + /** + * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $localeDateMock; + + /** + * @var \Magento\Backend\Block\Template\Context|\PHPUnit_Framework_MockObject_MockObject + */ + protected $contextMock; + + protected function setUp() { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -37,11 +48,25 @@ protected function setUp() $this->coreRegistryMock = $this->getMock('Magento\Framework\Registry', [], [], '', false); $this->adminHelperMock = $this->getMock('\Magento\Sales\Helper\Admin', [], [], '', false); + $this->contextMock = $this->getMockBuilder(\Magento\Backend\Block\Template\Context::class) + ->disableOriginalConstructor() + ->setMethods(['getLocaleDate']) + ->getMock(); + + $this->localeDateMock = $this->getMockBuilder(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::class) + ->getMock(); + + $this->contextMock->expects($this->any())->method('getLocaleDate')->will( + $this->returnValue($this->localeDateMock) + ); + $this->commentsHistory = $this->objectManager->getObject( 'Magento\Sales\Block\Adminhtml\Order\View\Tab\History', [ 'adminHelper' => $this->adminHelperMock, - 'registry' => $this->coreRegistryMock + 'registry' => $this->coreRegistryMock, + 'context' => $this->contextMock, + 'localeDate' => $this->localeDateMock ] ); } @@ -63,4 +88,39 @@ public function testGetItemCommentIsNotSet() $this->adminHelperMock->expects($this->never())->method('escapeHtmlWithLinks'); $this->assertEquals('', $this->commentsHistory->getItemComment($item)); } + + public function testGetItemCreatedAtDate() + { + $date = new \DateTime; + $item = ['created_at' => $date ]; + + $this->localeDateMock->expects($this->once()) + ->method('formatDateTime') + ->with($date, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::NONE) + ->willReturn('date'); + + $this->assertEquals('date', $this->commentsHistory->getItemCreatedAt($item)); + } + + public function testGetItemCreatedAtTime() + { + $date = new \DateTime; + $item = ['created_at' => $date ]; + + $this->localeDateMock->expects($this->once()) + ->method('formatDateTime') + ->with($date, \IntlDateFormatter::NONE, \IntlDateFormatter::MEDIUM) + ->willReturn('time'); + + $this->assertEquals('time', $this->commentsHistory->getItemCreatedAt($item, 'time')); + } + + public function testGetItemCreatedAtEmpty() + { + $item = ['title' => "Test" ]; + + $this->localeDateMock->expects($this->never())->method('formatDateTime'); + $this->assertEquals('', $this->commentsHistory->getItemCreatedAt($item)); + $this->assertEquals('', $this->commentsHistory->getItemCreatedAt($item, 'time')); + } } From 163efaee2382b1cc2255f2a9d007eb0a362c7569 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 7 Nov 2016 09:16:38 -0500 Subject: [PATCH 06/10] MAGETWO-56695: Paypal checkout not possible with products that have custom options #5938 - for 2.1 --- app/code/Magento/Catalog/Model/Product.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index 6c15997329918..5f6fce0bd0a27 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -1905,15 +1905,18 @@ public function addOption(Product\Option $option) */ public function getOptionById($optionId) { + $result = null; if (is_array($this->getOptions())) { /** @var \Magento\Catalog\Model\Product\Option $option */ foreach ($this->getOptions() as $option) { if ($option->getId() == $optionId) { - return $option; + $result = $option; + break; } } } - return null; + + return $result; } /** From 7fd1efd2665d943d4872f856c2ccc5bd1a4bd2bd Mon Sep 17 00:00:00 2001 From: lestare Date: Wed, 9 Nov 2016 13:53:43 +0200 Subject: [PATCH 07/10] =?UTF-8?q?MAGETWO-55612:=20=E2=80=9CNo=20Payment=20?= =?UTF-8?q?method=20available=E2=80=9D=20when=20customer=20tries=20to=20sh?= =?UTF-8?q?ip=20his=20items=20to=20billing=20restricted=20country=20for=20?= =?UTF-8?q?2.1.x?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/code/Magento/Braintree/Helper/Country.php | 16 +- app/code/Magento/Braintree/etc/di.xml | 19 +- .../js/view/payment/method-renderer/paypal.js | 18 +- .../Block/Checkout/LayoutProcessor.php | 234 ++++++++++----- app/code/Magento/Checkout/Helper/Data.php | 14 + .../BillingAddressDisplayOptions.php | 40 +++ .../Checkout/Model/DefaultConfigProvider.php | 16 +- .../Block/Checkout/LayoutProcessorTest.php | 276 ++++++++++++++++++ .../Magento/Checkout/etc/adminhtml/system.xml | 4 + .../web/js/action/set-billing-address.js | 19 +- .../frontend/web/js/view/billing-address.js | 48 ++- .../web/template/billing-address.html | 42 +-- .../CanUseForCountry/CountryProvider.php | 14 +- .../CanUseForCountry/CountryProviderTest.php | 130 +++++++-- .../css/source/module/checkout/_payments.less | 23 +- .../css/source/module/checkout/_payments.less | 22 +- 16 files changed, 722 insertions(+), 213 deletions(-) create mode 100644 app/code/Magento/Checkout/Model/Adminhtml/BillingAddressDisplayOptions.php create mode 100644 app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php diff --git a/app/code/Magento/Braintree/Helper/Country.php b/app/code/Magento/Braintree/Helper/Country.php index 3a3116b0d9ac0..fc62f45e79cc2 100644 --- a/app/code/Magento/Braintree/Helper/Country.php +++ b/app/code/Magento/Braintree/Helper/Country.php @@ -5,6 +5,7 @@ */ namespace Magento\Braintree\Helper; +use Magento\Braintree\Model\Adminhtml\System\Config\Country as CountryConfig; use Magento\Directory\Model\ResourceModel\Country\CollectionFactory; /** @@ -13,12 +14,12 @@ class Country { /** - * @var \Magento\Directory\Model\ResourceModel\Country\CollectionFactory + * @var CollectionFactory */ private $collectionFactory; /** - * @var \Magento\Braintree\Model\Adminhtml\System\Config\Country + * @var CountryConfig */ private $countryConfig; @@ -28,13 +29,11 @@ class Country private $countries; /** - * @param \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $factory - * @param \Magento\Braintree\Model\Adminhtml\System\Config\Country $countryConfig + * @param CollectionFactory $factory + * @param CountryConfig $countryConfig */ - public function __construct( - \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $factory, - \Magento\Braintree\Model\Adminhtml\System\Config\Country $countryConfig - ) { + public function __construct(CollectionFactory $factory, CountryConfig $countryConfig) + { $this->collectionFactory = $factory; $this->countryConfig = $countryConfig; } @@ -52,6 +51,7 @@ public function getCountries() ->loadData() ->toOptionArray(false); } + return $this->countries; } } diff --git a/app/code/Magento/Braintree/etc/di.xml b/app/code/Magento/Braintree/etc/di.xml index def12ff4c8a7e..dbf8515eb3f4d 100644 --- a/app/code/Magento/Braintree/etc/di.xml +++ b/app/code/Magento/Braintree/etc/di.xml @@ -22,6 +22,7 @@ Magento\Braintree\Model\Ui\ConfigProvider::PAYPAL_CODE BraintreePayPalInfo BraintreePayPalValueHandlerPool + BraintreePayPalValidatorPool BraintreePayPalCommandPool @@ -379,7 +380,7 @@ - + Magento\Braintree\Gateway\Config\Config @@ -392,6 +393,22 @@ + + + + + + Magento\Braintree\Gateway\Config\PayPal\Config + + + + + + BraintreePayPalCountryValidator + + + + diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js index 2b7aea3db5c4f..be7ea87e1f2cf 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js @@ -11,8 +11,18 @@ define([ 'Magento_Braintree/js/view/payment/adapter', 'Magento_Checkout/js/model/quote', 'Magento_Checkout/js/model/full-screen-loader', - 'Magento_Checkout/js/model/payment/additional-validators' -], function ($, _, Component, Braintree, quote, fullScreenLoader, additionalValidators) { + 'Magento_Checkout/js/model/payment/additional-validators', + 'Magento_Checkout/js/action/create-billing-address' +], function ( + $, + _, + Component, + Braintree, + quote, + fullScreenLoader, + additionalValidators, + createBillingAddress +) { 'use strict'; return Component.extend({ @@ -152,14 +162,16 @@ define([ var billingAddress = { street: [address.streetAddress], city: address.locality, - regionCode: address.region, postcode: address.postalCode, countryId: address.countryCodeAlpha2, + email: customer.email, firstname: customer.firstName, lastname: customer.lastName, telephone: customer.phone }; + billingAddress['region_code'] = address.region; + billingAddress = createBillingAddress(billingAddress); quote.billingAddress(billingAddress); }, diff --git a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php index 646137310cb51..b129226d63b6f 100644 --- a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php +++ b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php @@ -5,6 +5,7 @@ */ namespace Magento\Checkout\Block\Checkout; +use Magento\Checkout\Helper\Data; use Magento\Framework\App\ObjectManager; class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcessorInterface @@ -29,6 +30,11 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso */ private $options; + /** + * @var Data + */ + private $checkoutDataHelper; + /** * @param \Magento\Customer\Model\AttributeMetadataDataProvider $attributeMetadataDataProvider * @param \Magento\Ui\Component\Form\AttributeMapper $attributeMapper @@ -133,23 +139,12 @@ public function process($jsLayout) if (isset($jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children'] ['payment']['children'] )) { - if (!isset($jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children'] - ['payment']['children']['payments-list']['children'])) { - $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children'] - ['payment']['children']['payments-list']['children'] = []; - } - $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children'] - ['payment']['children']['payments-list']['children'] = - array_merge_recursive( - $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children'] - ['payment']['children']['payments-list']['children'], - $this->processPaymentConfiguration( - $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children'] - ['payment']['children']['renders']['children'], - $elements - ) - ); + ['payment']['children'] = $this->processPaymentChildrenComponents( + $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children'] + ['payment']['children'], + $elements + ); } if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step'] @@ -168,6 +163,50 @@ public function process($jsLayout) return $jsLayout; } + /** + * Appends billing address form component to payment layout + * + * @param array $paymentLayout + * @param array $elements + * + * @return array + */ + private function processPaymentChildrenComponents( + array $paymentLayout, + array $elements + ) { + if (!isset($paymentLayout['payments-list']['children'])) { + $paymentLayout['payments-list']['children'] = []; + } + + if (!isset($paymentLayout['afterMethods']['children'])) { + $paymentLayout['afterMethods']['children'] = []; + } + + // if billing address should be displayed on Payment method or page + if ($this->getCheckoutDataHelper()->isDisplayBillingOnPaymentMethodAvailable()) { + $paymentLayout['payments-list']['children'] = array_merge_recursive( + $paymentLayout['payments-list']['children'], + $this->processPaymentConfiguration( + $paymentLayout['renders']['children'], + $elements + ) + ); + } else { + $component['billing-address-form'] = $this->getBillingAddressComponent( + 'shared', + $elements + ); + + $paymentLayout['afterMethods']['children'] = array_merge_recursive( + $component, + $paymentLayout['afterMethods']['children'] + ); + } + + return $paymentLayout; + } + /** * Inject billing address component into every payment component * @@ -183,75 +222,108 @@ private function processPaymentConfiguration(array &$configuration, array $eleme if (empty($paymentComponent['isBillingAddressRequired'])) { continue; } - $output[$paymentCode . '-form'] = [ - 'component' => 'Magento_Checkout/js/view/billing-address', - 'displayArea' => 'billing-address-form-' . $paymentCode, - 'provider' => 'checkoutProvider', - 'deps' => 'checkoutProvider', - 'dataScopePrefix' => 'billingAddress' . $paymentCode, - 'sortOrder' => 1, - 'children' => [ - 'form-fields' => [ - 'component' => 'uiComponent', - 'displayArea' => 'additional-fieldsets', - 'children' => $this->merger->merge( - $elements, - 'checkoutProvider', - 'billingAddress' . $paymentCode, - [ - 'country_id' => [ - 'sortOrder' => 115, - ], - 'region' => [ - 'visible' => false, - ], - 'region_id' => [ - 'component' => 'Magento_Ui/js/form/element/region', - 'config' => [ - 'template' => 'ui/form/field', - 'elementTmpl' => 'ui/form/element/select', - 'customEntry' => 'billingAddress' . $paymentCode . '.region', - ], - 'validation' => [ - 'required-entry' => true, - ], - 'filterBy' => [ - 'target' => '${ $.provider }:${ $.parentScope }.country_id', - 'field' => 'country_id', - ], - ], - 'postcode' => [ - 'component' => 'Magento_Ui/js/form/element/post-code', - 'validation' => [ - 'required-entry' => true, - ], - ], - 'company' => [ - 'validation' => [ - 'min_text_length' => 0, - ], - ], - 'fax' => [ - 'validation' => [ - 'min_text_length' => 0, - ], - ], - 'telephone' => [ - 'config' => [ - 'tooltip' => [ - 'description' => __('For delivery questions.'), - ], - ], - ], - ] - ), - ], - ], - ]; + + $output[$paymentCode . '-form'] = $this->getBillingAddressComponent( + $paymentCode, + $elements + ); } unset($configuration[$paymentGroup]['methods']); } return $output; } + + /** + * Gets billing address component details + * + * @param string $paymentCode + * @param array $elements + * + * @return array + */ + private function getBillingAddressComponent($paymentCode, $elements) + { + return [ + 'component' => 'Magento_Checkout/js/view/billing-address', + 'displayArea' => 'billing-address-form-' . $paymentCode, + 'provider' => 'checkoutProvider', + 'deps' => 'checkoutProvider', + 'dataScopePrefix' => 'billingAddress' . $paymentCode, + 'sortOrder' => 1, + 'children' => [ + 'form-fields' => [ + 'component' => 'uiComponent', + 'displayArea' => 'additional-fieldsets', + 'children' => $this->merger->merge( + $elements, + 'checkoutProvider', + 'billingAddress' . $paymentCode, + [ + 'country_id' => [ + 'sortOrder' => 115, + ], + 'region' => [ + 'visible' => false, + ], + 'region_id' => [ + 'component' => 'Magento_Ui/js/form/element/region', + 'config' => [ + 'template' => 'ui/form/field', + 'elementTmpl' => 'ui/form/element/select', + 'customEntry' => 'billingAddress' . $paymentCode . '.region', + ], + 'validation' => [ + 'required-entry' => true, + ], + 'filterBy' => [ + 'target' => '${ $.provider }:${ $.parentScope }.country_id', + 'field' => 'country_id', + ], + ], + 'postcode' => [ + 'component' => 'Magento_Ui/js/form/element/post-code', + 'validation' => [ + 'required-entry' => true, + ], + ], + 'company' => [ + 'validation' => [ + 'min_text_length' => 0, + ], + ], + 'fax' => [ + 'validation' => [ + 'min_text_length' => 0, + ], + ], + 'telephone' => [ + 'config' => [ + 'tooltip' => [ + 'description' => __('For delivery questions.'), + ], + ], + ], + ] + ), + ], + ], + ]; + } + + /** + * Get checkout data helper instance + * + * @return Data + * @deprecated + */ + private function getCheckoutDataHelper() + { + if (!$this->checkoutDataHelper) { + $this->checkoutDataHelper = + ObjectManager::getInstance()->get(Data::class); + } + + return $this->checkoutDataHelper; + } } diff --git a/app/code/Magento/Checkout/Helper/Data.php b/app/code/Magento/Checkout/Helper/Data.php index 2073ffe87d4d6..b54d3187949e4 100644 --- a/app/code/Magento/Checkout/Helper/Data.php +++ b/app/code/Magento/Checkout/Helper/Data.php @@ -8,6 +8,7 @@ use Magento\Framework\Pricing\PriceCurrencyInterface; use Magento\Quote\Model\Quote\Item\AbstractItem; use Magento\Store\Model\Store; +use Magento\Store\Model\ScopeInterface; /** * Checkout default helper @@ -400,4 +401,17 @@ public function isCustomerMustBeLogged() \Magento\Store\Model\ScopeInterface::SCOPE_STORE ); } + + /** + * Checks if display billing address on payment method is available, otherwise + * billing address should be display on payment page + * @return bool + */ + public function isDisplayBillingOnPaymentMethodAvailable() + { + return (bool) !$this->scopeConfig->getValue( + 'checkout/options/display_billing_address_on', + ScopeInterface::SCOPE_STORE + ); + } } diff --git a/app/code/Magento/Checkout/Model/Adminhtml/BillingAddressDisplayOptions.php b/app/code/Magento/Checkout/Model/Adminhtml/BillingAddressDisplayOptions.php new file mode 100644 index 0000000000000..5ff7df90abede --- /dev/null +++ b/app/code/Magento/Checkout/Model/Adminhtml/BillingAddressDisplayOptions.php @@ -0,0 +1,40 @@ + 'Payment Method', 'value' => 0], + * ['label' => 'Payment Page', 'value' => 1] + * ] + */ + public function toOptionArray() + { + return [ + [ + 'label' => __('Payment Method'), + 'value' => 0, + ], + [ + 'label' => __('Payment Page'), + 'value' => 1, + ], + ]; + } +} diff --git a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php index 923e54aac9378..51a1e3d138a36 100644 --- a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php +++ b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php @@ -5,25 +5,22 @@ */ namespace Magento\Checkout\Model; +use Magento\Catalog\Helper\Product\ConfigurationPool; use Magento\Checkout\Helper\Data as CheckoutHelper; use Magento\Checkout\Model\Session as CheckoutSession; use Magento\Customer\Api\CustomerRepositoryInterface as CustomerRepository; use Magento\Customer\Model\Context as CustomerContext; -use Magento\Customer\Model\Registration as CustomerRegistration; use Magento\Customer\Model\Session as CustomerSession; use Magento\Customer\Model\Url as CustomerUrlManager; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Http\Context as HttpContext; use Magento\Framework\Data\Form\FormKey; -use Magento\Framework\Locale\CurrencyInterface as CurrencyManager; -use Magento\Quote\Api\CartRepositoryInterface; -use Magento\Quote\Api\CartItemRepositoryInterface as QuoteItemRepository; -use Magento\Quote\Api\ShippingMethodManagementInterface as ShippingMethodManager; -use Magento\Catalog\Helper\Product\ConfigurationPool; -use Magento\Quote\Model\QuoteIdMaskFactory; use Magento\Framework\Locale\FormatInterface as LocaleFormat; use Magento\Framework\UrlInterface; +use Magento\Quote\Api\CartItemRepositoryInterface as QuoteItemRepository; use Magento\Quote\Api\CartTotalRepositoryInterface; -use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Quote\Api\ShippingMethodManagementInterface as ShippingMethodManager; +use Magento\Quote\Model\QuoteIdMaskFactory; use Magento\Store\Model\ScopeInterface; /** @@ -296,6 +293,9 @@ public function getConfig() $output['originCountryCode'] = $this->getOriginCountryCode(); $output['paymentMethods'] = $this->getPaymentMethods(); $output['autocomplete'] = $this->isAutocompleteEnabled(); + $output['displayBillingOnPaymentMethod'] = + $this->checkoutHelper->isDisplayBillingOnPaymentMethodAvailable(); + return $output; } diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php new file mode 100644 index 0000000000000..1351213f990b5 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php @@ -0,0 +1,276 @@ +attributeDataProvider = $this->getMockBuilder(AttributeMetadataDataProvider::class) + ->disableOriginalConstructor() + ->setMethods(['loadAttributesCollection']) + ->getMock(); + + $this->attributeMapper = $this->getMockBuilder(AttributeMapper::class) + ->disableOriginalConstructor() + ->setMethods(['map']) + ->getMock(); + + $this->attributeMerger = $this->getMockBuilder(AttributeMerger::class) + ->disableOriginalConstructor() + ->setMethods(['merge']) + ->getMock(); + + $this->dataHelper = $this->getMockBuilder(Data::class) + ->disableOriginalConstructor() + ->setMethods(['isDisplayBillingOnPaymentMethodAvailable']) + ->getMock(); + + $options = $this->getMockBuilder(Options::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->layoutProcessor = new LayoutProcessor( + $this->attributeDataProvider, + $this->attributeMapper, + $this->attributeMerger + ); + + $objectManager->setBackwardCompatibleProperty($this->layoutProcessor, 'checkoutDataHelper', $this->dataHelper); + $objectManager->setBackwardCompatibleProperty($this->layoutProcessor, 'options', $options); + } + + /** + * @covers \Magento\Checkout\Block\Checkout\LayoutProcessor::process + */ + public function testProcess() + { + $jsLayout = $this->getLayoutData(); + + $this->attributeDataProvider->expects(static::once()) + ->method('loadAttributesCollection') + ->willReturn([]); + + $this->dataHelper->expects(static::once()) + ->method('isDisplayBillingOnPaymentMethodAvailable') + ->willReturn(true); + + $this->attributeMerger->expects(static::exactly(2)) + ->method('merge') + ->willReturnMap([ + ['payment1_1' => $this->getBillingComponent('payment1_1')], + ['payment2_1' => $this->getBillingComponent('payment2_1')], + ]); + + $actual = $this->layoutProcessor->process($jsLayout); + + static::assertArrayHasKey( + 'payment1_1-form', + $actual['components']['checkout']['children']['steps']['children']['billing-step']['children'] + ['payment']['children']['payments-list']['children'] + ); + static::assertArrayHasKey( + 'payment2_1-form', + $actual['components']['checkout']['children']['steps']['children']['billing-step']['children'] + ['payment']['children']['payments-list']['children'] + ); + static::assertArrayNotHasKey( + 'payment2_2-form', + $actual['components']['checkout']['children']['steps']['children']['billing-step']['children'] + ['payment']['children']['payments-list']['children'] + ); + static::assertArrayHasKey( + 'afterMethods', + $actual['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children'] + ); + static::assertEmpty( + $actual['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['afterMethods']['children'] + ); + } + + /** + * @covers \Magento\Checkout\Block\Checkout\LayoutProcessor::process + */ + public function testProcessWithBillingAddressOnPaymentPage() + { + $jsLayout = $this->getLayoutData(); + + $this->attributeDataProvider->expects(static::once()) + ->method('loadAttributesCollection') + ->willReturn([]); + + $this->dataHelper->expects(static::once()) + ->method('isDisplayBillingOnPaymentMethodAvailable') + ->willReturn(false); + + $this->attributeMerger->expects(static::once()) + ->method('merge') + ->willReturn($this->getBillingComponent('shared')); + + $actual = $this->layoutProcessor->process($jsLayout); + + static::assertEmpty( + $actual['components']['checkout']['children']['steps']['children']['billing-step']['children'] + ['payment']['children']['payments-list']['children'] + ); + + static::assertNotEmpty( + $actual['components']['checkout']['children']['steps']['children']['billing-step']['children'] + ['payment']['children']['afterMethods']['children'] + ); + static::assertArrayHasKey( + 'billing-address-form', + $actual['components']['checkout']['children']['steps']['children']['billing-step']['children']['payment'] + ['children']['afterMethods']['children'] + ); + } + + /** + * Get mock layout data for testing + * @return array + */ + private function getLayoutData() + { + return [ + 'components' => [ + 'checkout' => [ + 'children' => [ + 'steps' => [ + 'children' => [ + 'billing-step' => [ + 'children' => [ + 'payment' => [ + 'children' => [ + 'renders' => [ + 'children' => [ + 'payment1' => [ + 'methods' => [ + 'payment1_1' => [ + 'isBillingAddressRequired' => true + ] + ] + ], + 'payment2' => [ + 'methods' => [ + 'payment2_1' => [ + 'isBillingAddressRequired' => true + ], + 'payment2_2' => [ + 'isBillingAddressRequired' => false + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ]; + } + + /** + * Get mock data for billing component + * @param string $paymentCode + * @return array + */ + private function getBillingComponent($paymentCode) + { + return [ + 'country_id' => [ + 'sortOrder' => 115, + ], + 'region' => [ + 'visible' => false, + ], + 'region_id' => [ + 'component' => 'Magento_Ui/js/form/element/region', + 'config' => [ + 'template' => 'ui/form/field', + 'elementTmpl' => 'ui/form/element/select', + 'customEntry' => 'billingAddress' . $paymentCode . '.region', + ], + 'validation' => [ + 'required-entry' => true, + ], + 'filterBy' => [ + 'target' => '${ $.provider }:${ $.parentScope }.country_id', + 'field' => 'country_id', + ], + ], + 'postcode' => [ + 'component' => 'Magento_Ui/js/form/element/post-code', + 'validation' => [ + 'required-entry' => true, + ], + ], + 'company' => [ + 'validation' => [ + 'min_text_length' => 0, + ], + ], + 'fax' => [ + 'validation' => [ + 'min_text_length' => 0, + ], + ], + 'telephone' => [ + 'config' => [ + 'tooltip' => [ + 'description' => __('For delivery questions.'), + ], + ], + ], + ]; + } +} diff --git a/app/code/Magento/Checkout/etc/adminhtml/system.xml b/app/code/Magento/Checkout/etc/adminhtml/system.xml index d4567a4382539..b3b3d11b568a3 100644 --- a/app/code/Magento/Checkout/etc/adminhtml/system.xml +++ b/app/code/Magento/Checkout/etc/adminhtml/system.xml @@ -21,6 +21,10 @@ Magento\Config\Model\Config\Source\Yesno + + + \Magento\Checkout\Model\Adminhtml\BillingAddressDisplayOptions + diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/set-billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/action/set-billing-address.js index 31d52e5dd1d76..2fc853a35003a 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/set-billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/set-billing-address.js @@ -10,7 +10,6 @@ define( 'mage/storage', 'Magento_Checkout/js/model/error-processor', 'Magento_Customer/js/model/customer', - 'Magento_Checkout/js/action/get-totals', 'Magento_Checkout/js/model/full-screen-loader', 'Magento_Checkout/js/action/get-payment-information' ], @@ -20,10 +19,8 @@ define( storage, errorProcessor, customer, - getTotalsAction, fullScreenLoader, - getPaymentInformationAction - ) { + getPaymentInformationAction) { 'use strict'; return function (messageContainer) { @@ -55,18 +52,12 @@ define( serviceUrl, JSON.stringify(payload) ).done( function () { - var deferred = null; + var deferred = $.Deferred(); - if (!quote.isVirtual()) { - getTotalsAction([]); + getPaymentInformationAction(deferred); + $.when(deferred).done(function () { fullScreenLoader.stopLoader(); - } else { - deferred = $.Deferred(); - getPaymentInformationAction(deferred); - $.when(deferred).done(function () { - fullScreenLoader.stopLoader(); - }); - } + }); } ).fail( function (response) { diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js index b9cf58b51b133..0c2e7fb01c701 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js @@ -7,6 +7,7 @@ define( [ 'ko', + 'underscore', 'Magento_Ui/js/form/form', 'Magento_Customer/js/model/customer', 'Magento_Customer/js/model/address-list', @@ -22,6 +23,7 @@ define( ], function ( ko, + _, Component, customer, addressList, @@ -39,9 +41,13 @@ define( var lastSelectedBillingAddress = null, newAddressOption = { + /** + * Get new address label + * @returns {String} + */ getAddressInline: function () { - return $t('New Address'); - }, + return $t('New Address'); + }, customerAddressId: null }, countryData = customerData.get('directory-data'), @@ -121,9 +127,8 @@ define( useShippingAddress: function () { if (this.isAddressSameAsShipping()) { selectBillingAddress(quote.shippingAddress()); - if (window.checkoutConfig.reloadOnBillingAddress) { - setBillingAddressAction(globalMessageList); - } + + this.updateAddresses(); this.isAddressDetailsVisible(true); } else { lastSelectedBillingAddress = quote.billingAddress(); @@ -142,15 +147,13 @@ define( if (this.selectedAddress() && this.selectedAddress() != newAddressOption) { selectBillingAddress(this.selectedAddress()); checkoutData.setSelectedBillingAddress(this.selectedAddress().getKey()); - if (window.checkoutConfig.reloadOnBillingAddress) { - setBillingAddressAction(globalMessageList); - } } else { this.source.set('params.invalid', false); this.source.trigger(this.dataScopePrefix + '.data.validate'); + if (this.source.get(this.dataScopePrefix + '.custom_attributes')) { this.source.trigger(this.dataScopePrefix + '.custom_attributes.data.validate'); - }; + } if (!this.source.get('params.invalid')) { var addressData = this.source.get(this.dataScopePrefix), @@ -159,19 +162,16 @@ define( if (customer.isLoggedIn() && !this.customerHasAddresses) { this.saveInAddressBook(1); } - addressData.save_in_address_book = this.saveInAddressBook() ? 1 : 0; + addressData['save_in_address_book'] = this.saveInAddressBook() ? 1 : 0; newBillingAddress = createBillingAddress(addressData); // New address must be selected as a billing address selectBillingAddress(newBillingAddress); checkoutData.setSelectedBillingAddress(newBillingAddress.getKey()); checkoutData.setNewCustomerBillingAddress(addressData); - - if (window.checkoutConfig.reloadOnBillingAddress) { - setBillingAddressAction(globalMessageList); - } } } + this.updateAddresses(); }, /** @@ -222,6 +222,26 @@ define( */ getCountryName: function (countryId) { return countryData()[countryId] != undefined ? countryData()[countryId].name : ''; + }, + + /** + * Trigger action to update shipping and billing addresses + */ + updateAddresses: function () { + if (window.checkoutConfig.reloadOnBillingAddress || + !window.checkoutConfig.displayBillingOnPaymentMethod + ) { + setBillingAddressAction(globalMessageList); + } + }, + + /** + * Get code + * @param {Object} parent + * @returns {String} + */ + getCode: function (parent) { + return _.isFunction(parent.getCode) ? parent.getCode() : 'shared'; } }); } diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html index 377208aa1b8ee..6ec32291647e6 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html @@ -4,23 +4,29 @@ * See COPYING.txt for license details. */ --> -
- - -
+
- -
- - -
-
- - -
+
+ +
-
+ + +
+ + +
+
+ + +
+
+
+ +
diff --git a/app/code/Magento/Payment/Model/Checks/CanUseForCountry/CountryProvider.php b/app/code/Magento/Payment/Model/Checks/CanUseForCountry/CountryProvider.php index 8342b181d5e6f..d15920ff91cbe 100644 --- a/app/code/Magento/Payment/Model/Checks/CanUseForCountry/CountryProvider.php +++ b/app/code/Magento/Payment/Model/Checks/CanUseForCountry/CountryProvider.php @@ -5,8 +5,9 @@ */ namespace Magento\Payment\Model\Checks\CanUseForCountry; -use Magento\Quote\Model\Quote; use Magento\Directory\Helper\Data as DirectoryHelper; +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\Quote\Address; class CountryProvider { @@ -27,13 +28,14 @@ public function __construct(DirectoryHelper $directoryHelper) * Get payment country * * @param Quote $quote - * @return int + * + * @return string */ public function getCountry(Quote $quote) { - $address = $quote->isVirtual() ? $quote->getBillingAddress() : $quote->getShippingAddress(); - return $address - ? $address->getCountry() - : $this->directoryHelper->getDefaultCountry(); + /** @var Address $address */ + $address = $quote->getBillingAddress() ?: $quote->getShippingAddress(); + + return $address->getCountry() ? : $this->directoryHelper->getDefaultCountry(); } } diff --git a/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCountry/CountryProviderTest.php b/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCountry/CountryProviderTest.php index dd33a4c0b877d..022d6ff359c76 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCountry/CountryProviderTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCountry/CountryProviderTest.php @@ -5,55 +5,123 @@ */ namespace Magento\Payment\Test\Unit\Model\Checks\CanUseForCountry; +use Magento\Directory\Helper\Data; +use Magento\Payment\Model\Checks\CanUseForCountry\CountryProvider; +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\Quote\Address; +use PHPUnit_Framework_MockObject_MockObject as MockObject; + +/** + * CountryProviderTest contains tests for CountryProvider class + */ class CountryProviderTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Payment\Model\Checks\CanUseForCountry\CountryProvider + * @var CountryProvider */ - protected $model; + private $countryProvider; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var Data|MockObject */ - protected $directoryMock; + private $directory; + + /** + * @var Quote|MockObject + */ + private $quote; protected function setUp() { - $this->directoryMock = $this->getMock('Magento\Directory\Helper\Data', [], [], '', false, false); - $this->model = new \Magento\Payment\Model\Checks\CanUseForCountry\CountryProvider($this->directoryMock); + $this->directory = $this->getMockBuilder(Data::class) + ->disableOriginalConstructor() + ->setMethods(['getDefaultCountry']) + ->getMock(); + + $this->quote = $this->getMockBuilder(Quote::class) + ->disableOriginalConstructor() + ->setMethods(['getBillingAddress', 'getShippingAddress']) + ->getMock(); + + $this->countryProvider = new CountryProvider($this->directory); } - public function testGetCountryForNonVirtualQuote() + /** + * @covers \Magento\Payment\Model\Checks\CanUseForCountry\CountryProvider::getCountry + */ + public function testGetCountry() { - $quoteMock = $this->getMock('Magento\Quote\Model\Quote', [], [], '', false, false); - $quoteMock->expects($this->once())->method('isVirtual')->willReturn(false); - $addressMock = $this->getMock('Magento\Quote\Model\Quote\Address', [], [], '', false, false); - $addressMock->expects($this->once())->method('getCountry')->will($this->returnValue(1)); - $quoteMock->expects($this->once())->method('getShippingAddress')->will($this->returnValue($addressMock)); - $this->assertEquals(1, $this->model->getCountry($quoteMock)); + $address = $this->getMockBuilder(Address::class) + ->disableOriginalConstructor() + ->setMethods(['getCountry']) + ->getMock(); + + $this->quote->expects(static::once()) + ->method('getBillingAddress') + ->willReturn($address); + + $this->quote->expects(static::never()) + ->method('getShippingAddress'); + + $address->expects(static::once()) + ->method('getCountry') + ->willReturn('UK'); + $this->directory->expects(static::never()) + ->method('getDefaultCountry'); + + static::assertEquals('UK', $this->countryProvider->getCountry($this->quote)); } - public function testGetCountryForVirtualQuoteWhenBillingAddressNotExist() + /** + * @covers \Magento\Payment\Model\Checks\CanUseForCountry\CountryProvider::getCountry + */ + public function testGetCountryForBillingAddressWithoutCountry() { - $quoteMock = $this->getMock('Magento\Quote\Model\Quote', [], [], '', false, false); - $quoteMock->expects($this->once())->method('isVirtual')->willReturn(true); - $addressMock = $this->getMock('Magento\Quote\Model\Quote\Address', [], [], '', false, false); - $addressMock->expects($this->never())->method('getCountry'); - $quoteMock->expects($this->never())->method('getShippingAddress'); - $quoteMock->expects($this->once())->method('getBillingAddress')->willReturn(null); - $this->directoryMock->expects($this->once())->method('getDefaultCountry')->willReturn(10); - $this->assertEquals(10, $this->model->getCountry($quoteMock)); + $address = $this->getMockBuilder(Address::class) + ->disableOriginalConstructor() + ->setMethods(['getCountry']) + ->getMock(); + + $this->quote->expects(static::never()) + ->method('getShippingAddress'); + $this->quote->expects(static::once()) + ->method('getBillingAddress') + ->willReturn($address); + + $address->expects(static::once()) + ->method('getCountry') + ->willReturn(null); + $this->directory->expects(static::once()) + ->method('getDefaultCountry') + ->willReturn('US'); + static::assertEquals('US', $this->countryProvider->getCountry($this->quote)); } - public function testGetCountryForVirtualQuoteWhenBillingAddressExist() + /** + * @covers \Magento\Payment\Model\Checks\CanUseForCountry\CountryProvider::getCountry + */ + public function testGetCountryShippingAddress() { - $quoteMock = $this->getMock('Magento\Quote\Model\Quote', [], [], '', false, false); - $quoteMock->expects($this->once())->method('isVirtual')->willReturn(true); - $addressMock = $this->getMock('Magento\Quote\Model\Quote\Address', [], [], '', false, false); - $addressMock->expects($this->once())->method('getCountry')->willReturn(10); - $quoteMock->expects($this->never())->method('getShippingAddress'); - $quoteMock->expects($this->once())->method('getBillingAddress')->willReturn($addressMock); - $this->directoryMock->expects($this->never())->method('getDefaultCountry'); - $this->assertEquals(10, $this->model->getCountry($quoteMock)); + $address = $this->getMockBuilder(Address::class) + ->disableOriginalConstructor() + ->setMethods(['getCountry']) + ->getMock(); + + $this->quote->expects(static::once()) + ->method('getBillingAddress') + ->willReturn(null); + + $this->quote->expects(static::once()) + ->method('getShippingAddress') + ->willReturn($address); + + $address->expects(static::once()) + ->method('getCountry') + ->willReturn('CA'); + + $this->directory->expects(static::never()) + ->method('getDefaultCountry'); + + static::assertEquals('CA', $this->countryProvider->getCountry($this->quote)); } } diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less index ca69275441643..7731595870f06 100644 --- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less @@ -72,7 +72,6 @@ .payment-method-content { display: none; - .lib-css(padding, 0 0 @indent__base @checkout-payment-method-content__padding__xl); .fieldset { &:not(:last-child) { @@ -90,7 +89,7 @@ margin: 0 0 @indent__s; } - .payment-method-billing-address { + .checkout-billing-address { margin: 0 0 @indent__base; .primary { @@ -106,15 +105,11 @@ .billing-address-details { .lib-css(line-height, @checkout-billing-address-details__line-height); .lib-css(padding, @checkout-billing-address-details__padding); - - .action-edit-address { - &:extend(.abs-action-button-as-link all); - } } } .payment-method-note { - & + .payment-method-billing-address { + & + .checkout-billing-address { margin-top: @indent__base; } } @@ -161,7 +156,7 @@ .lib-css(padding, 0 @checkout-payment-method-title-mobile__padding @indent__base); } - .payment-method-billing-address { + .checkout-billing-address { .action-cancel { margin-top: @indent__s; } @@ -175,12 +170,10 @@ .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .checkout-payment-method { - .payment-methods { - .actions-toolbar { - .primary { - float: right; - margin: 0; - } + .actions-toolbar { + .primary { + float: right; + margin: 0; } } @@ -214,7 +207,7 @@ } } - .payment-method-billing-address { + .checkout-billing-address { .action-update { float: right; } diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less index 3c3ee77ed00e0..85b2e96e6ea4a 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less @@ -89,7 +89,7 @@ margin: 0 0 @indent__s; } - .payment-method-billing-address { + .checkout-billing-address { margin: 0 0 @indent__base; .primary { @@ -105,15 +105,11 @@ .billing-address-details { .lib-css(line-height, @checkout-billing-address-details__line-height); .lib-css(padding, @checkout-billing-address-details__padding); - - .action-edit-address { - &:extend(.abs-action-button-as-link all); - } } } .payment-method-note { - & + .payment-method-billing-address { + & + .checkout-billing-address { margin-top: @indent__base; } } @@ -160,7 +156,7 @@ .lib-css(padding, 0 @checkout-payment-method-title-mobile__padding @indent__base); } - .payment-method-billing-address { + .checkout-billing-address { .action-cancel { margin-top: @indent__s; } @@ -174,12 +170,10 @@ .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .checkout-payment-method { - .payment-methods { - .actions-toolbar { - .primary { - float: right; - margin: 0; - } + .actions-toolbar { + .primary { + float: right; + margin: 0; } } @@ -193,7 +187,7 @@ } } - .payment-method-billing-address { + .checkout-billing-address { .action-update { float: right; } From 8991de3a31167e52e8a30ae477959cff11f638a1 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun Date: Thu, 10 Nov 2016 10:37:07 +0200 Subject: [PATCH 08/10] MAGETWO-60248: Billing Address and Default Shipping Address checkboxes on Customer page are saved incorrectly --- .../Controller/Adminhtml/Index/Save.php | 10 +- .../Controller/Adminhtml/Index/SaveTest.php | 120 +++++------------- 2 files changed, 37 insertions(+), 93 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php index 949d53bbdd43e..3d897bda1df36 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php @@ -13,9 +13,7 @@ use Magento\Customer\Model\Metadata\Form; use Magento\Framework\Exception\LocalizedException; -/** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ + class Save extends \Magento\Customer\Controller\Adminhtml\Index { /** @@ -81,6 +79,7 @@ protected function _extractData( ) { $metadataForm = $metadataForm ? $metadataForm : $this->getMetadataForm($entityType, $formCode, $scope); $formData = $metadataForm->extractData($request, $scope); + $formData = $metadataForm->compactData($formData); // Initialize additional attributes /** @var \Magento\Framework\DataObject $object */ @@ -90,11 +89,6 @@ protected function _extractData( $formData[$attributeCode] = isset($requestData[$attributeCode]) ? $requestData[$attributeCode] : false; } - $result = $metadataForm->compactData($formData); - - // Re-initialize additional attributes - $formData = array_replace($formData, $result); - // Unset unused attributes $formAttributes = $metadataForm->getAttributes(); foreach ($formAttributes as $attribute) { diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php index 7813690cea780..b064a2d9ee094 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php @@ -302,33 +302,30 @@ public function testExecuteWithExistentCustomer() ], 'subscription' => $subscription, ]; - $filteredData = [ + $extractedData = [ 'entity_id' => $customerId, 'code' => 'value', 'coolness' => false, 'disable_auto_group_change' => 'false', ]; - $dataToCompact = [ + $compactedData = [ 'entity_id' => $customerId, 'code' => 'value', 'coolness' => false, 'disable_auto_group_change' => 'false', - CustomerInterface::DEFAULT_BILLING => false, - CustomerInterface::DEFAULT_SHIPPING => false, - 'confirmation' => false, - 'sendemail_store_id' => false, - 'extension_attributes' => false, + CustomerInterface::DEFAULT_BILLING => 2, + CustomerInterface::DEFAULT_SHIPPING => 2 ]; - $addressFilteredData = [ + $addressExtractedData = [ 'entity_id' => $addressId, - 'default_billing' => 'true', - 'default_shipping' => 'true', +/* 'default_billing' => 'true', + 'default_shipping' => 'true',*/ 'code' => 'value', 'coolness' => false, 'region' => 'region', 'region_id' => 'region_id', ]; - $addressDataToCompact = [ + $addressCompactedData = [ 'entity_id' => $addressId, 'default_billing' => 'true', 'default_shipping' => 'true', @@ -428,11 +425,11 @@ public function testExecuteWithExistentCustomer() $customerFormMock->expects($this->once()) ->method('extractData') ->with($this->requestMock, 'customer') - ->willReturn($filteredData); + ->willReturn($extractedData); $customerFormMock->expects($this->once()) ->method('compactData') - ->with($dataToCompact) - ->willReturn($filteredData); + ->with($extractedData) + ->willReturn($compactedData); $customerFormMock->expects($this->once()) ->method('getAttributes') ->willReturn($attributes); @@ -443,11 +440,11 @@ public function testExecuteWithExistentCustomer() $customerAddressFormMock->expects($this->once()) ->method('extractData') ->with($this->requestMock, 'address/' . $addressId) - ->willReturn($addressFilteredData); + ->willReturn($addressExtractedData); $customerAddressFormMock->expects($this->once()) ->method('compactData') - ->with($addressDataToCompact) - ->willReturn($addressFilteredData); + ->with($addressExtractedData) + ->willReturn($addressCompactedData); $customerAddressFormMock->expects($this->once()) ->method('getAttributes') ->willReturn($attributes); @@ -635,33 +632,13 @@ public function testExecuteWithNewCustomer() ], 'subscription' => $subscription, ]; - $filteredData = [ + $extractedData = [ 'coolness' => false, 'disable_auto_group_change' => 'false', ]; - $dataToCompact = [ - 'coolness' => false, - 'disable_auto_group_change' => 'false', - CustomerInterface::DEFAULT_BILLING => false, - CustomerInterface::DEFAULT_SHIPPING => false, - 'confirmation' => false, - 'sendemail_store_id' => false, - 'extension_attributes' => false, - ]; - $addressFilteredData = [ + $addressExtractedData = [ 'entity_id' => $addressId, - 'default_billing' => 'false', - 'default_shipping' => 'false', - 'code' => 'value', - 'coolness' => false, - 'region' => 'region', - 'region_id' => 'region_id', - ]; - $addressDataToCompact = [ - 'entity_id' => $addressId, - 'default_billing' => 'false', - 'default_shipping' => 'false', - 'code' => 'value', + 'code' => 'value', 'coolness' => false, 'region' => 'region', 'region_id' => 'region_id', @@ -739,11 +716,11 @@ public function testExecuteWithNewCustomer() $customerFormMock->expects($this->once()) ->method('extractData') ->with($this->requestMock, 'customer') - ->willReturn($filteredData); + ->willReturn($extractedData); $customerFormMock->expects($this->once()) ->method('compactData') - ->with($dataToCompact) - ->willReturn($filteredData); + ->with($extractedData) + ->willReturn($extractedData); $customerFormMock->expects($this->once()) ->method('getAttributes') ->willReturn($attributes); @@ -754,11 +731,11 @@ public function testExecuteWithNewCustomer() $customerAddressFormMock->expects($this->once()) ->method('extractData') ->with($this->requestMock, 'address/' . $addressId) - ->willReturn($addressFilteredData); + ->willReturn($addressExtractedData); $customerAddressFormMock->expects($this->once()) ->method('compactData') - ->with($addressDataToCompact) - ->willReturn($addressFilteredData); + ->with($addressExtractedData) + ->willReturn($addressExtractedData); $customerAddressFormMock->expects($this->once()) ->method('getAttributes') ->willReturn($attributes); @@ -912,19 +889,10 @@ public function testExecuteWithNewCustomerAndValidationException() ], 'subscription' => $subscription, ]; - $filteredData = [ + $extractedData = [ 'coolness' => false, 'disable_auto_group_change' => 'false', ]; - $dataToCompact = [ - 'coolness' => false, - 'disable_auto_group_change' => 'false', - CustomerInterface::DEFAULT_BILLING => false, - CustomerInterface::DEFAULT_SHIPPING => false, - 'confirmation' => false, - 'sendemail_store_id' => false, - 'extension_attributes' => false, - ]; /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $customerFormMock */ $attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface') @@ -973,11 +941,11 @@ public function testExecuteWithNewCustomerAndValidationException() $customerFormMock->expects($this->once()) ->method('extractData') ->with($this->requestMock, 'customer') - ->willReturn($filteredData); + ->willReturn($extractedData); $customerFormMock->expects($this->once()) ->method('compactData') - ->with($dataToCompact) - ->willReturn($filteredData); + ->with($extractedData) + ->willReturn($extractedData); $customerFormMock->expects($this->once()) ->method('getAttributes') ->willReturn($attributes); @@ -1064,18 +1032,9 @@ public function testExecuteWithNewCustomerAndLocalizedException() ], 'subscription' => $subscription, ]; - $filteredData = [ - 'coolness' => false, - 'disable_auto_group_change' => 'false', - ]; - $dataToCompact = [ + $extractedData = [ 'coolness' => false, 'disable_auto_group_change' => 'false', - CustomerInterface::DEFAULT_BILLING => false, - CustomerInterface::DEFAULT_SHIPPING => false, - 'confirmation' => false, - 'sendemail_store_id' => false, - 'extension_attributes' => false, ]; /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $customerFormMock */ @@ -1126,11 +1085,11 @@ public function testExecuteWithNewCustomerAndLocalizedException() $customerFormMock->expects($this->once()) ->method('extractData') ->with($this->requestMock, 'customer') - ->willReturn($filteredData); + ->willReturn($extractedData); $customerFormMock->expects($this->once()) ->method('compactData') - ->with($dataToCompact) - ->willReturn($filteredData); + ->with($extractedData) + ->willReturn($extractedData); $customerFormMock->expects($this->once()) ->method('getAttributes') ->willReturn($attributes); @@ -1216,19 +1175,10 @@ public function testExecuteWithNewCustomerAndException() ], 'subscription' => $subscription, ]; - $filteredData = [ + $extractedData = [ 'coolness' => false, 'disable_auto_group_change' => 'false', ]; - $dataToCompact = [ - 'coolness' => false, - 'disable_auto_group_change' => 'false', - CustomerInterface::DEFAULT_BILLING => false, - CustomerInterface::DEFAULT_SHIPPING => false, - 'confirmation' => false, - 'sendemail_store_id' => false, - 'extension_attributes' => false, - ]; /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $customerFormMock */ $attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface') @@ -1277,11 +1227,11 @@ public function testExecuteWithNewCustomerAndException() $customerFormMock->expects($this->once()) ->method('extractData') ->with($this->requestMock, 'customer') - ->willReturn($filteredData); + ->willReturn($extractedData); $customerFormMock->expects($this->once()) ->method('compactData') - ->with($dataToCompact) - ->willReturn($filteredData); + ->with($extractedData) + ->willReturn($extractedData); $customerFormMock->expects($this->once()) ->method('getAttributes') ->willReturn($attributes); From 093a625df9f22ee40356ea698ec3c9dd9a8e4438 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun Date: Thu, 10 Nov 2016 11:00:40 +0200 Subject: [PATCH 09/10] MAGETWO-60248: Billing Address and Default Shipping Address checkboxes on Customer page are saved incorrectly --- .../Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php index b064a2d9ee094..26dc30d7530fb 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php @@ -318,8 +318,6 @@ public function testExecuteWithExistentCustomer() ]; $addressExtractedData = [ 'entity_id' => $addressId, -/* 'default_billing' => 'true', - 'default_shipping' => 'true',*/ 'code' => 'value', 'coolness' => false, 'region' => 'region', From 6fb56bb370d1407ed214ab8680b5295f0554af86 Mon Sep 17 00:00:00 2001 From: lestare Date: Thu, 10 Nov 2016 11:49:17 +0200 Subject: [PATCH 10/10] =?UTF-8?q?MAGETWO-55612:=20=E2=80=9CNo=20Payment=20?= =?UTF-8?q?method=20available=E2=80=9D=20when=20customer=20tries=20to=20sh?= =?UTF-8?q?ip=20his=20items=20to=20billing=20restricted=20country=20for=20?= =?UTF-8?q?2.1.x?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CanUseForCountry/CountryProvider.php | 11 ++++-- .../CanUseForCountry/CountryProviderTest.php | 38 ++++++++++++++----- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/Payment/Model/Checks/CanUseForCountry/CountryProvider.php b/app/code/Magento/Payment/Model/Checks/CanUseForCountry/CountryProvider.php index d15920ff91cbe..9d72705ed2876 100644 --- a/app/code/Magento/Payment/Model/Checks/CanUseForCountry/CountryProvider.php +++ b/app/code/Magento/Payment/Model/Checks/CanUseForCountry/CountryProvider.php @@ -33,9 +33,14 @@ public function __construct(DirectoryHelper $directoryHelper) */ public function getCountry(Quote $quote) { - /** @var Address $address */ - $address = $quote->getBillingAddress() ?: $quote->getShippingAddress(); + /** @var string $country */ + $country = $quote->getBillingAddress()->getCountry() ? : + $quote->getShippingAddress()->getCountry(); - return $address->getCountry() ? : $this->directoryHelper->getDefaultCountry(); + if (!$country) { + $country = $this->directoryHelper->getDefaultCountry(); + } + + return $country; } } diff --git a/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCountry/CountryProviderTest.php b/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCountry/CountryProviderTest.php index 022d6ff359c76..bb120e4377264 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCountry/CountryProviderTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCountry/CountryProviderTest.php @@ -77,20 +77,31 @@ public function testGetCountry() */ public function testGetCountryForBillingAddressWithoutCountry() { - $address = $this->getMockBuilder(Address::class) + $billingAddress = $this->getMockBuilder(Address::class) + ->disableOriginalConstructor() + ->setMethods(['getCountry']) + ->getMock(); + + $shippingAddress = $this->getMockBuilder(Address::class) ->disableOriginalConstructor() ->setMethods(['getCountry']) ->getMock(); - $this->quote->expects(static::never()) - ->method('getShippingAddress'); + $this->quote->expects(static::once()) + ->method('getShippingAddress') + ->willReturn($shippingAddress); $this->quote->expects(static::once()) ->method('getBillingAddress') - ->willReturn($address); + ->willReturn($billingAddress); - $address->expects(static::once()) + $billingAddress->expects(static::once()) + ->method('getCountry') + ->willReturn(null); + + $shippingAddress->expects(static::once()) ->method('getCountry') ->willReturn(null); + $this->directory->expects(static::once()) ->method('getDefaultCountry') ->willReturn('US'); @@ -102,23 +113,32 @@ public function testGetCountryForBillingAddressWithoutCountry() */ public function testGetCountryShippingAddress() { - $address = $this->getMockBuilder(Address::class) + $shippingAddress = $this->getMockBuilder(Address::class) + ->disableOriginalConstructor() + ->setMethods(['getCountry']) + ->getMock(); + + $billingAddress = $this->getMockBuilder(Address::class) ->disableOriginalConstructor() ->setMethods(['getCountry']) ->getMock(); $this->quote->expects(static::once()) ->method('getBillingAddress') - ->willReturn(null); + ->willReturn($billingAddress); $this->quote->expects(static::once()) ->method('getShippingAddress') - ->willReturn($address); + ->willReturn($shippingAddress); - $address->expects(static::once()) + $shippingAddress->expects(static::once()) ->method('getCountry') ->willReturn('CA'); + $shippingAddress->expects(static::once()) + ->method('getCountry') + ->willReturn(null); + $this->directory->expects(static::never()) ->method('getDefaultCountry');