diff --git a/app/code/Magento/Checkout/Controller/Sidebar/RemoveItem.php b/app/code/Magento/Checkout/Controller/Sidebar/RemoveItem.php index 90c0ad1ac4cab221c3ba08cc1c8cf2cb29ccdf25..1097b3becf007396800e4c15cbc38fe56233caa4 100644 --- a/app/code/Magento/Checkout/Controller/Sidebar/RemoveItem.php +++ b/app/code/Magento/Checkout/Controller/Sidebar/RemoveItem.php @@ -11,6 +11,7 @@ use Magento\Framework\App\Action\Context; use Magento\Framework\App\Response\Http; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Json\Helper\Data; +use Magento\Framework\View\Result\PageFactory; use Psr\Log\LoggerInterface; class RemoveItem extends Action @@ -30,15 +31,22 @@ class RemoveItem extends Action */ protected $jsonHelper; + /** + * @var PageFactory + */ + protected $resultPageFactory; + public function __construct( Context $context, Sidebar $sidebar, LoggerInterface $logger, - Data $jsonHelper + Data $jsonHelper, + PageFactory $resultPageFactory ) { $this->sidebar = $sidebar; $this->logger = $logger; $this->jsonHelper = $jsonHelper; + $this->resultPageFactory = $resultPageFactory; parent::__construct($context); } @@ -70,9 +78,8 @@ class RemoveItem extends Action { $response = $this->sidebar->getResponseData($error); if (isset($response['cleanup']) && (bool)$response['cleanup']) { - $this->_view->loadLayout(['default'], true, true, false); - $layout = $this->_view->getLayout(); - $block = $layout->getBlock('minicart.content')->toHtml(); + $resultPage = $this->resultPageFactory->create(); + $block = $resultPage->getLayout()->getBlock('minicart.content')->toHtml(); $response['content'] = $block; } return $this->getResponse()->representJson( diff --git a/app/code/Magento/Checkout/Model/Sidebar.php b/app/code/Magento/Checkout/Model/Sidebar.php index 7dc9fd93e8bb00c54e6a137801cd6623e0ba4553..225c5c7323bc48cc3d06f970acfa59b5a99d6965 100644 --- a/app/code/Magento/Checkout/Model/Sidebar.php +++ b/app/code/Magento/Checkout/Model/Sidebar.php @@ -10,6 +10,7 @@ use Magento\Checkout\Model\Cart; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Locale\ResolverInterface; use Magento\Quote\Api\Data\CartItemInterface; +use Magento\Quote\Model\Quote\Address\Total; class Sidebar { @@ -56,25 +57,23 @@ class Sidebar */ public function getResponseData($error = '') { - $response = [ - 'success' => empty($error) ? true : false, - ]; - if ($response['success']) { - if (!$this->getSummaryQty()) { - $response['cleanup'] = true; - } - $response = array_merge($response, [ + if (empty($error)) { + $response = [ + 'success' => true, 'data' => [ 'summary_qty' => $this->getSummaryQty(), 'summary_text' => $this->getSummaryText(), 'subtotal' => $this->getSubtotalHtml(), ], - ]); - } - if (!empty($error)){ - $response = array_merge($response, [ + ]; + if (!$this->getSummaryQty()) { + $response['cleanup'] = true; + } + } else { + $response = [ + 'success' => false, 'error_message' => $error, - ]); + ]; } return $response; } @@ -171,7 +170,9 @@ class Sidebar protected function getSubtotalHtml() { $totals = $this->cart->getQuote()->getTotals(); - $subtotal = isset($totals['subtotal']) ? $totals['subtotal']->getValue() : 0; + $subtotal = isset($totals['subtotal']) && $totals['subtotal'] instanceof Total + ? $totals['subtotal']->getValue() + : 0; return $this->helperData->formatPrice($subtotal); } } diff --git a/app/code/Magento/Checkout/Test/Unit/Controller/Sidebar/RemoveItemTest.php b/app/code/Magento/Checkout/Test/Unit/Controller/Sidebar/RemoveItemTest.php new file mode 100644 index 0000000000000000000000000000000000000000..900693acec908f43bb86e24f10f89e0d04585bb4 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Unit/Controller/Sidebar/RemoveItemTest.php @@ -0,0 +1,234 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Test\Unit\Controller\Sidebar; + +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +class RemoveItemTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Checkout\Controller\Sidebar\RemoveItem */ + protected $removeItem; + + /** @var ObjectManagerHelper */ + protected $objectManagerHelper; + + /** @var \Magento\Checkout\Model\Sidebar|\PHPUnit_Framework_MockObject_MockObject */ + protected $sidebarMock; + + /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $loggerMock; + + /** @var \Magento\Framework\Json\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */ + protected $jsonHelperMock; + + /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $requestMock; + + /** @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $responseMock; + + /** @var \Magento\Framework\View\Result\PageFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $resultPageFactoryMock; + + protected function setUp() + { + $this->sidebarMock = $this->getMock('Magento\Checkout\Model\Sidebar', [], [], '', false); + $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface'); + $this->jsonHelperMock = $this->getMock('Magento\Framework\Json\Helper\Data', [], [], '', false); + $this->requestMock = $this->getMock('Magento\Framework\App\RequestInterface'); + $this->responseMock = $this->getMockForAbstractClass( + 'Magento\Framework\App\ResponseInterface', + [], + '', + false, + true, + true, + ['representJson'] + ); + $this->resultPageFactoryMock = $this->getMock('Magento\Framework\View\Result\PageFactory', [], [], '', false); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->removeItem = $this->objectManagerHelper->getObject( + 'Magento\Checkout\Controller\Sidebar\RemoveItem', + [ + 'sidebar' => $this->sidebarMock, + 'logger' => $this->loggerMock, + 'jsonHelper' => $this->jsonHelperMock, + 'request' => $this->requestMock, + 'response' => $this->responseMock, + 'resultPageFactory' => $this->resultPageFactoryMock, + ] + ); + } + + public function testExecute() + { + $this->requestMock->expects($this->once()) + ->method('getParam') + ->with('item_id', null) + ->willReturn('1'); + + $this->sidebarMock->expects($this->once()) + ->method('checkQuoteItem') + ->with(1) + ->willReturnSelf(); + $this->sidebarMock->expects($this->once()) + ->method('removeQuoteItem') + ->with(1) + ->willReturnSelf(); + $this->sidebarMock->expects($this->once()) + ->method('getResponseData') + ->with('') + ->willReturn( + [ + 'cleanup' => true, + 'data' => [ + 'summary_qty' => 0, + 'summary_text' => __(' items'), + 'subtotal' => 0, + ], + ] + ); + + $pageMock = $this->getMockBuilder('Magento\Framework\View\Result\Page') + ->disableOriginalConstructor() + ->getMock(); + + $this->resultPageFactoryMock->expects($this->once()) + ->method('create') + ->with(false, []) + ->willReturn($pageMock); + + $layoutMock = $this->getMockBuilder('Magento\Framework\View\LayoutInterface') + ->getMock(); + + $pageMock->expects($this->once()) + ->method('getLayout') + ->willReturn($layoutMock); + + $blockMock = $this->getMockBuilder('Magento\Framework\View\Element\BlockInterface') + ->getMock(); + + $layoutMock->expects($this->once()) + ->method('getBlock') + ->with('minicart.content') + ->willReturn($blockMock); + + $blockMock->expects($this->once()) + ->method('toHtml') + ->willReturn('block html'); + + $this->jsonHelperMock->expects($this->once()) + ->method('jsonEncode') + ->with( + [ + 'cleanup' => true, + 'data' => [ + 'summary_qty' => 0, + 'summary_text' => __(' items'), + 'subtotal' => 0, + ], + 'content' => 'block html', + ] + ) + ->willReturn('json encoded'); + + $this->responseMock->expects($this->once()) + ->method('representJson') + ->with('json encoded') + ->willReturn('json represented'); + + $this->assertEquals('json represented', $this->removeItem->execute()); + } + + public function testExecuteWithLocalizedException() + { + $this->requestMock->expects($this->once()) + ->method('getParam') + ->with('item_id', null) + ->willReturn('1'); + + $this->sidebarMock->expects($this->once()) + ->method('checkQuoteItem') + ->with(1) + ->willThrowException(new LocalizedException(__('Error message!'))); + + $this->sidebarMock->expects($this->once()) + ->method('getResponseData') + ->with('Error message!') + ->willReturn( + [ + 'success' => false, + 'error_message' => 'Error message!', + ] + ); + + $this->jsonHelperMock->expects($this->once()) + ->method('jsonEncode') + ->with( + [ + 'success' => false, + 'error_message' => 'Error message!', + ] + ) + ->willReturn('json encoded'); + + $this->responseMock->expects($this->once()) + ->method('representJson') + ->with('json encoded') + ->willReturn('json represented'); + + $this->assertEquals('json represented', $this->removeItem->execute()); + } + + public function testExecuteWithException() + { + $this->requestMock->expects($this->once()) + ->method('getParam') + ->with('item_id', null) + ->willReturn('1'); + + $exception = new \Exception('Error message!'); + + $this->sidebarMock->expects($this->once()) + ->method('checkQuoteItem') + ->with(1) + ->willThrowException($exception); + + $this->loggerMock->expects($this->once()) + ->method('critical') + ->with($exception) + ->willReturn(null); + + $this->sidebarMock->expects($this->once()) + ->method('getResponseData') + ->with('Error message!') + ->willReturn( + [ + 'success' => false, + 'error_message' => 'Error message!', + ] + ); + + $this->jsonHelperMock->expects($this->once()) + ->method('jsonEncode') + ->with( + [ + 'success' => false, + 'error_message' => 'Error message!', + ] + ) + ->willReturn('json encoded'); + + $this->responseMock->expects($this->once()) + ->method('representJson') + ->with('json encoded') + ->willReturn('json represented'); + + $this->assertEquals('json represented', $this->removeItem->execute()); + } +} diff --git a/app/code/Magento/Checkout/Test/Unit/Controller/Sidebar/UpdateItemQtyTest.php b/app/code/Magento/Checkout/Test/Unit/Controller/Sidebar/UpdateItemQtyTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b36cbed010b0298348affe01da90822694fd8cb0 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Unit/Controller/Sidebar/UpdateItemQtyTest.php @@ -0,0 +1,210 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Test\Unit\Controller\Sidebar; + +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +class UpdateItemQtyTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Checkout\Controller\Sidebar\UpdateItemQty */ + protected $updateItemQty; + + /** @var ObjectManagerHelper */ + protected $objectManagerHelper; + + /** @var \Magento\Checkout\Model\Sidebar|\PHPUnit_Framework_MockObject_MockObject */ + protected $sidebarMock; + + /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $loggerMock; + + /** @var \Magento\Framework\Json\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */ + protected $jsonHelperMock; + + /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $requestMock; + + /** @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $responseMock; + + protected function setUp() + { + $this->sidebarMock = $this->getMock('Magento\Checkout\Model\Sidebar', [], [], '', false); + $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface'); + $this->jsonHelperMock = $this->getMock('Magento\Framework\Json\Helper\Data', [], [], '', false); + $this->requestMock = $this->getMock('Magento\Framework\App\RequestInterface'); + $this->responseMock = $this->getMockForAbstractClass( + 'Magento\Framework\App\ResponseInterface', + [], + '', + false, + true, + true, + ['representJson'] + ); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->updateItemQty = $this->objectManagerHelper->getObject( + 'Magento\Checkout\Controller\Sidebar\UpdateItemQty', + [ + 'sidebar' => $this->sidebarMock, + 'logger' => $this->loggerMock, + 'jsonHelper' => $this->jsonHelperMock, + 'request' => $this->requestMock, + 'response' => $this->responseMock, + ] + ); + } + + public function testExecute() + { + $this->requestMock->expects($this->at(0)) + ->method('getParam') + ->with('item_id', null) + ->willReturn('1'); + $this->requestMock->expects($this->at(1)) + ->method('getParam') + ->with('item_qty', null) + ->willReturn('2'); + + $this->sidebarMock->expects($this->once()) + ->method('checkQuoteItem') + ->with(1) + ->willReturnSelf(); + $this->sidebarMock->expects($this->once()) + ->method('updateQuoteItem') + ->with(1, 2) + ->willReturnSelf(); + $this->sidebarMock->expects($this->once()) + ->method('getResponseData') + ->with('') + ->willReturn( + [ + 'data' => [ + 'summary_qty' => 2, + 'summary_text' => __(' items'), + 'subtotal' => 12.34, + ], + ] + ); + + $this->jsonHelperMock->expects($this->once()) + ->method('jsonEncode') + ->with( + [ + 'data' => [ + 'summary_qty' => 2, + 'summary_text' => __(' items'), + 'subtotal' => 12.34, + ], + ] + ) + ->willReturn('json encoded'); + + $this->responseMock->expects($this->once()) + ->method('representJson') + ->with('json encoded') + ->willReturn('json represented'); + + $this->assertEquals('json represented', $this->updateItemQty->execute()); + } + + public function testExecuteWithLocalizedException() + { + $this->requestMock->expects($this->at(0)) + ->method('getParam') + ->with('item_id', null) + ->willReturn('1'); + $this->requestMock->expects($this->at(1)) + ->method('getParam') + ->with('item_qty', null) + ->willReturn('2'); + + $this->sidebarMock->expects($this->once()) + ->method('checkQuoteItem') + ->with(1) + ->willThrowException(new LocalizedException(__('Error!'))); + + $this->sidebarMock->expects($this->once()) + ->method('getResponseData') + ->with('Error!') + ->willReturn( + [ + 'success' => false, + 'error_message' => 'Error!', + ] + ); + + $this->jsonHelperMock->expects($this->once()) + ->method('jsonEncode') + ->with( + [ + 'success' => false, + 'error_message' => 'Error!', + ] + ) + ->willReturn('json encoded'); + + $this->responseMock->expects($this->once()) + ->method('representJson') + ->with('json encoded') + ->willReturn('json represented'); + + $this->assertEquals('json represented', $this->updateItemQty->execute()); + } + + public function testExecuteWithException() + { + $this->requestMock->expects($this->at(0)) + ->method('getParam') + ->with('item_id', null) + ->willReturn('1'); + $this->requestMock->expects($this->at(1)) + ->method('getParam') + ->with('item_qty', null) + ->willReturn('2'); + + $exception = new \Exception('Error!'); + + $this->sidebarMock->expects($this->once()) + ->method('checkQuoteItem') + ->with(1) + ->willThrowException($exception); + + $this->loggerMock->expects($this->once()) + ->method('critical') + ->with($exception) + ->willReturn(null); + + $this->sidebarMock->expects($this->once()) + ->method('getResponseData') + ->with('Error!') + ->willReturn( + [ + 'success' => false, + 'error_message' => 'Error!', + ] + ); + + $this->jsonHelperMock->expects($this->once()) + ->method('jsonEncode') + ->with( + [ + 'success' => false, + 'error_message' => 'Error!', + ] + ) + ->willReturn('json encoded'); + + $this->responseMock->expects($this->once()) + ->method('representJson') + ->with('json encoded') + ->willReturn('json represented'); + + $this->assertEquals('json represented', $this->updateItemQty->execute()); + } +} diff --git a/app/code/Magento/Checkout/Test/Unit/Model/SidebarTest.php b/app/code/Magento/Checkout/Test/Unit/Model/SidebarTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c928db0923da844cdecd741b08269824d726a6f5 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Unit/Model/SidebarTest.php @@ -0,0 +1,233 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Test\Unit\Model; + +use Magento\Checkout\Model\Sidebar; + +class SidebarTest extends \PHPUnit_Framework_TestCase +{ + /** @var Sidebar */ + protected $sidebar; + + /** @var \Magento\Checkout\Model\Cart|\PHPUnit_Framework_MockObject_MockObject */ + protected $cartMock; + + /** @var \Magento\Checkout\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */ + protected $checkoutHelperMock; + + /** @var \Magento\Framework\Locale\ResolverInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $resolverMock; + + protected function setUp() + { + $this->cartMock = $this->getMock('Magento\Checkout\Model\Cart', [], [], '', false); + $this->checkoutHelperMock = $this->getMock('Magento\Checkout\Helper\Data', [], [], '', false); + $this->resolverMock = $this->getMock('Magento\Framework\Locale\ResolverInterface'); + + $this->sidebar = new Sidebar( + $this->cartMock, + $this->checkoutHelperMock, + $this->resolverMock + ); + } + + /** + * @param string $error + * @param float $summaryQty + * @param array $totals + * @param array $result + * + * @dataProvider dataProviderGetResponseData + */ + public function testGetResponseData($error, $summaryQty, $totals, $result) + { + $quoteMock = $this->getMockBuilder('Magento\Quote\Model\Quote') + ->disableOriginalConstructor() + ->getMock(); + $quoteMock->expects($this->any()) + ->method('getTotals') + ->willReturn($totals); + + $this->cartMock->expects($this->any()) + ->method('getSummaryQty') + ->willReturn($summaryQty); + $this->cartMock->expects($this->any()) + ->method('getQuote') + ->willReturn($quoteMock); + + $this->checkoutHelperMock->expects($this->any()) + ->method('formatPrice') + ->willReturnArgument(0); + + $this->assertEquals($result, $this->sidebar->getResponseData($error)); + } + + public function dataProviderGetResponseData() + { + $totalMock = $this->getMockBuilder('Magento\Quote\Model\Quote\Address\Total') + ->disableOriginalConstructor() + ->setMethods(['getValue']) + ->getMock(); + $totalMock->expects($this->any()) + ->method('getValue') + ->willReturn(12.34); + + return [ + [ + '', + 0, + [], + [ + 'success' => true, + 'data' => [ + 'summary_qty' => 0, + 'summary_text' => __(' items'), + 'subtotal' => 0, + ], + 'cleanup' => true, + ], + ], + [ + '', + 1, + [ + 'subtotal' => $this->getMock('NonexistentClass'), + ], + [ + 'success' => true, + 'data' => [ + 'summary_qty' => 1, + 'summary_text' => __(' item'), + 'subtotal' => 0, + ], + ], + ], + [ + '', + 2, + [ + 'subtotal' => $totalMock, + ], + [ + 'success' => true, + 'data' => [ + 'summary_qty' => 2, + 'summary_text' => __(' items'), + 'subtotal' => 12.34, + ], + ], + ], + [ + 'Error', + 0, + [], + [ + 'success' => false, + 'error_message' => 'Error', + ], + ], + ]; + } + + public function testCheckQuoteItem() + { + $itemId = 1; + + $itemMock = $this->getMockBuilder('Magento\Quote\Api\Data\CartItemInterface') + ->getMock(); + + $quoteMock = $this->getMockBuilder('Magento\Quote\Model\Quote') + ->disableOriginalConstructor() + ->getMock(); + $quoteMock->expects($this->once()) + ->method('getItemById') + ->with($itemId) + ->willReturn($itemMock); + + $this->cartMock->expects($this->any()) + ->method('getQuote') + ->willReturn($quoteMock); + + $this->assertEquals($this->sidebar, $this->sidebar->checkQuoteItem($itemId)); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @exceptedExceptionMessage We can't find the quote item. + */ + public function testCheckQuoteItemWithException() + { + $itemId = 2; + + $quoteMock = $this->getMockBuilder('Magento\Quote\Model\Quote') + ->disableOriginalConstructor() + ->getMock(); + $quoteMock->expects($this->once()) + ->method('getItemById') + ->with($itemId) + ->willReturn(null); + + $this->cartMock->expects($this->any()) + ->method('getQuote') + ->willReturn($quoteMock); + + $this->sidebar->checkQuoteItem($itemId); + } + + public function testRemoveQuoteItem() + { + $itemId = 1; + + $this->cartMock->expects($this->once()) + ->method('removeItem') + ->with($itemId) + ->willReturnSelf(); + $this->cartMock->expects($this->once()) + ->method('save') + ->willReturnSelf(); + + $this->assertEquals($this->sidebar, $this->sidebar->removeQuoteItem($itemId)); + } + + public function testUpdateQuoteItem() + { + $itemId = 1; + $itemQty = 2; + + $this->resolverMock->expects($this->once()) + ->method('getLocale') + ->willReturn('en'); + + $this->cartMock->expects($this->once()) + ->method('updateItems') + ->with([$itemId => ['qty' => $itemQty]]) + ->willReturnSelf(); + $this->cartMock->expects($this->once()) + ->method('save') + ->willReturnSelf(); + + $this->assertEquals($this->sidebar, $this->sidebar->updateQuoteItem($itemId, $itemQty)); + } + + public function testUpdateQuoteItemWithZeroQty() + { + $itemId = 1; + $itemQty = 0; + + $this->resolverMock->expects($this->never()) + ->method('getLocale'); + + $this->cartMock->expects($this->once()) + ->method('updateItems') + ->with([$itemId => ['qty' => $itemQty]]) + ->willReturnSelf(); + $this->cartMock->expects($this->once()) + ->method('save') + ->willReturnSelf(); + + $this->assertEquals($this->sidebar, $this->sidebar->updateQuoteItem($itemId, $itemQty)); + } +}