diff --git a/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php b/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php index f370c49cdfa20..e0a92ea0e0bea 100644 --- a/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php +++ b/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php @@ -115,7 +115,8 @@ protected function wrapResult($html) { return '
' . $html . '
'; } diff --git a/app/code/Magento/Catalog/Test/Unit/Pricing/Render/FinalPriceBoxTest.php b/app/code/Magento/Catalog/Test/Unit/Pricing/Render/FinalPriceBoxTest.php index e4f19e550a170..90384c122f095 100644 --- a/app/code/Magento/Catalog/Test/Unit/Pricing/Render/FinalPriceBoxTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Pricing/Render/FinalPriceBoxTest.php @@ -246,7 +246,8 @@ public function testRenderMsrpEnabled() //assert price wrapper $this->assertEquals( - '
test
', + '
test
', $result ); } diff --git a/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php index 08f5bbf1383a2..2502b79921e99 100644 --- a/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php @@ -74,6 +74,11 @@ class Configurable extends \Magento\Catalog\Block\Product\View\AbstractView */ private $customerSession; + /** + * @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices + */ + private $variationPrices; + /** * @param \Magento\Catalog\Block\Product\Context $context * @param \Magento\Framework\Stdlib\ArrayUtils $arrayUtils @@ -86,6 +91,7 @@ class Configurable extends \Magento\Catalog\Block\Product\View\AbstractView * @param array $data * @param Format|null $localeFormat * @param Session|null $customerSession + * @param \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices|null $variationPrices * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -99,7 +105,8 @@ public function __construct( ConfigurableAttributeData $configurableAttributeData, array $data = [], Format $localeFormat = null, - Session $customerSession = null + Session $customerSession = null, + \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices $variationPrices = null ) { $this->priceCurrency = $priceCurrency; $this->helper = $helper; @@ -109,6 +116,9 @@ public function __construct( $this->configurableAttributeData = $configurableAttributeData; $this->localeFormat = $localeFormat ?: ObjectManager::getInstance()->get(Format::class); $this->customerSession = $customerSession ?: ObjectManager::getInstance()->get(Session::class); + $this->variationPrices = $variationPrices ?: ObjectManager::getInstance()->get( + \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices::class + ); parent::__construct( $context, @@ -211,9 +221,6 @@ public function getJsonConfig() $store = $this->getCurrentStore(); $currentProduct = $this->getProduct(); - $regularPrice = $currentProduct->getPriceInfo()->getPrice('regular_price'); - $finalPrice = $currentProduct->getPriceInfo()->getPrice('final_price'); - $options = $this->helper->getOptions($currentProduct, $this->getAllowProducts()); $attributesData = $this->configurableAttributeData->getAttributesData($currentProduct, $options); @@ -223,17 +230,7 @@ public function getJsonConfig() 'currencyFormat' => $store->getCurrentCurrency()->getOutputFormat(), 'optionPrices' => $this->getOptionPrices(), 'priceFormat' => $this->localeFormat->getPriceFormat(), - 'prices' => [ - 'oldPrice' => [ - 'amount' => $this->localeFormat->getNumber($regularPrice->getAmount()->getValue()), - ], - 'basePrice' => [ - 'amount' => $this->localeFormat->getNumber($finalPrice->getAmount()->getBaseAmount()), - ], - 'finalPrice' => [ - 'amount' => $this->localeFormat->getNumber($finalPrice->getAmount()->getValue()), - ], - ], + 'prices' => $this->variationPrices->getFormattedPrices($this->getProduct()->getPriceInfo()), 'productId' => $currentProduct->getId(), 'chooseText' => __('Choose an Option...'), 'images' => $this->getOptionImages(), diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Variations/Prices.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Variations/Prices.php new file mode 100644 index 0000000000000..a60730b06fad2 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Variations/Prices.php @@ -0,0 +1,51 @@ +localeFormat = $localeFormat; + } + + /** + * Get product prices for configurable variations + * + * @param \Magento\Framework\Pricing\PriceInfo\Base $priceInfo + * @return array + */ + public function getFormattedPrices(\Magento\Framework\Pricing\PriceInfo\Base $priceInfo) + { + $regularPrice = $priceInfo->getPrice('regular_price'); + $finalPrice = $priceInfo->getPrice('final_price'); + + return [ + 'oldPrice' => [ + 'amount' => $this->localeFormat->getNumber($regularPrice->getAmount()->getValue()), + ], + 'basePrice' => [ + 'amount' => $this->localeFormat->getNumber($finalPrice->getAmount()->getBaseAmount()), + ], + 'finalPrice' => [ + 'amount' => $this->localeFormat->getNumber($finalPrice->getAmount()->getValue()), + ], + ]; + } +} diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Block/Product/View/Type/ConfigurableTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Block/Product/View/Type/ConfigurableTest.php index db3c30e3b4e33..b45306d670bff 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Block/Product/View/Type/ConfigurableTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Block/Product/View/Type/ConfigurableTest.php @@ -78,6 +78,11 @@ class ConfigurableTest extends \PHPUnit\Framework\TestCase */ private $customerSession; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $variationPricesMock; + protected function setUp() { $this->mockContextObject(); @@ -144,6 +149,10 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); + $this->variationPricesMock = $this->createMock( + \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices::class + ); + $this->block = new \Magento\ConfigurableProduct\Block\Product\View\Type\Configurable( $this->context, $this->arrayUtils, @@ -155,7 +164,8 @@ protected function setUp() $this->configurableAttributeData, [], $this->localeFormat, - $this->customerSession + $this->customerSession, + $this->variationPricesMock ); } @@ -260,12 +270,8 @@ public function testGetJsonConfig() 'getAmount', ]) ->getMockForAbstractClass(); - $priceMock->expects($this->any()) - ->method('getAmount') - ->willReturn($amountMock); - + $priceMock->expects($this->any())->method('getAmount')->willReturn($amountMock); $tierPriceMock = $this->getTierPriceMock($amountMock, $priceQty, $percentage); - $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) ->disableOriginalConstructor() ->getMock(); @@ -283,27 +289,16 @@ public function testGetJsonConfig() ['tier_price', $tierPriceMock], ]); - $productMock->expects($this->any()) - ->method('getTypeInstance') - ->willReturn($productTypeMock); - $productMock->expects($this->any()) - ->method('getPriceInfo') - ->willReturn($priceInfoMock); - $productMock->expects($this->any()) - ->method('isSaleable') - ->willReturn(true); - $productMock->expects($this->any()) - ->method('getId') - ->willReturn($productId); + $productMock->expects($this->any())->method('getTypeInstance')->willReturn($productTypeMock); + $productMock->expects($this->any())->method('getPriceInfo')->willReturn($priceInfoMock); + $productMock->expects($this->any())->method('isSaleable')->willReturn(true); + $productMock->expects($this->any())->method('getId')->willReturn($productId); $this->helper->expects($this->any()) ->method('getOptions') ->with($productMock, [$productMock]) ->willReturn([]); - - $this->product->expects($this->any()) - ->method('getSkipSaleableCheck') - ->willReturn(true); + $this->product->expects($this->any())->method('getSkipSaleableCheck')->willReturn(true); $attributesData = [ 'attributes' => [], @@ -315,9 +310,7 @@ public function testGetJsonConfig() ->with($productMock, []) ->willReturn($attributesData); - $this->localeFormat->expects($this->any()) - ->method('getPriceFormat') - ->willReturn([]); + $this->localeFormat->expects($this->atLeastOnce())->method('getPriceFormat')->willReturn([]); $this->localeFormat->expects($this->any()) ->method('getNumber') ->willReturnMap([ @@ -326,16 +319,29 @@ public function testGetJsonConfig() [$percentage, $percentage], ]); + $this->variationPricesMock->expects($this->once()) + ->method('getFormattedPrices') + ->with($priceInfoMock) + ->willReturn( + [ + 'oldPrice' => [ + 'amount' => $amount, + ], + 'basePrice' => [ + 'amount' => $amount, + ], + 'finalPrice' => [ + 'amount' => $amount, + ], + ] + ); + $expectedArray = $this->getExpectedArray($productId, $amount, $priceQty, $percentage); $expectedJson = json_encode($expectedArray); - $this->jsonEncoder->expects($this->once()) - ->method('encode') - ->with($expectedArray) - ->willReturn($expectedJson); + $this->jsonEncoder->expects($this->once())->method('encode')->with($expectedArray)->willReturn($expectedJson); $this->block->setData('product', $productMock); - $result = $this->block->getJsonConfig(); $this->assertEquals($expectedJson, $result); } diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/Configurable/Variations/PricesTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/Configurable/Variations/PricesTest.php new file mode 100644 index 0000000000000..6d7067666989c --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/Configurable/Variations/PricesTest.php @@ -0,0 +1,60 @@ +localeFormatMock = $this->createMock(\Magento\Framework\Locale\Format::class); + $this->model = new \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices( + $this->localeFormatMock + ); + } + + public function testGetFormattedPrices() + { + $expected = [ + 'oldPrice' => [ + 'amount' => 500 + ], + 'basePrice' => [ + 'amount' => 1000 + ], + 'finalPrice' => [ + 'amount' => 500 + ] + ]; + $priceInfoMock = $this->createMock(\Magento\Framework\Pricing\PriceInfo\Base::class); + $priceMock = $this->createMock(\Magento\Framework\Pricing\Price\PriceInterface::class); + $priceInfoMock->expects($this->atLeastOnce())->method('getPrice')->willReturn($priceMock); + + $amountMock = $this->createMock(\Magento\Framework\Pricing\Amount\AmountInterface::class); + $amountMock->expects($this->atLeastOnce())->method('getValue')->willReturn(500); + $amountMock->expects($this->atLeastOnce())->method('getBaseAmount')->willReturn(1000); + $priceMock->expects($this->atLeastOnce())->method('getAmount')->willReturn($amountMock); + + $this->localeFormatMock->expects($this->atLeastOnce()) + ->method('getNumber') + ->withConsecutive([500], [1000], [500]) + ->will($this->onConsecutiveCalls(500, 1000, 500)); + + $this->assertEquals($expected, $this->model->getFormattedPrices($priceInfoMock)); + } +} diff --git a/app/code/Magento/Swatches/Block/Product/Renderer/Listing/Configurable.php b/app/code/Magento/Swatches/Block/Product/Renderer/Listing/Configurable.php index 6a42ad1cc9849..85633475205ed 100644 --- a/app/code/Magento/Swatches/Block/Product/Renderer/Listing/Configurable.php +++ b/app/code/Magento/Swatches/Block/Product/Renderer/Listing/Configurable.php @@ -5,16 +5,94 @@ */ namespace Magento\Swatches\Block\Product\Renderer\Listing; +use Magento\Catalog\Block\Product\Context; +use Magento\Catalog\Helper\Product as CatalogProduct; use Magento\Catalog\Model\Product; +use Magento\ConfigurableProduct\Helper\Data; +use Magento\ConfigurableProduct\Model\ConfigurableAttributeData; +use Magento\Customer\Helper\Session\CurrentCustomer; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Json\EncoderInterface; +use Magento\Framework\Pricing\PriceCurrencyInterface; +use Magento\Framework\Stdlib\ArrayUtils; +use Magento\Swatches\Helper\Data as SwatchData; +use Magento\Swatches\Helper\Media; +use Magento\Swatches\Model\SwatchAttributesProvider; /** * Swatch renderer block in Category page * * @api * @since 100.0.2 + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Configurable extends \Magento\Swatches\Block\Product\Renderer\Configurable { + /** + * @var \Magento\Framework\Locale\Format + */ + private $localeFormat; + + /** + * @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices + */ + private $variationPrices; + + /** + * @param Context $context + * @param ArrayUtils $arrayUtils + * @param EncoderInterface $jsonEncoder + * @param Data $helper + * @param CatalogProduct $catalogProduct + * @param CurrentCustomer $currentCustomer + * @param PriceCurrencyInterface $priceCurrency + * @param ConfigurableAttributeData $configurableAttributeData + * @param SwatchData $swatchHelper + * @param Media $swatchMediaHelper + * @param array $data other data + * @param SwatchAttributesProvider $swatchAttributesProvider + * @param \Magento\Framework\Locale\Format|null $localeFormat + * @param \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices|null $variationPrices + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function __construct( + Context $context, + ArrayUtils $arrayUtils, + EncoderInterface $jsonEncoder, + Data $helper, + CatalogProduct $catalogProduct, + CurrentCustomer $currentCustomer, + PriceCurrencyInterface $priceCurrency, + ConfigurableAttributeData $configurableAttributeData, + SwatchData $swatchHelper, + Media $swatchMediaHelper, + array $data = [], + SwatchAttributesProvider $swatchAttributesProvider = null, + \Magento\Framework\Locale\Format $localeFormat = null, + \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices $variationPrices = null + ) { + parent::__construct( + $context, + $arrayUtils, + $jsonEncoder, + $helper, + $catalogProduct, + $currentCustomer, + $priceCurrency, + $configurableAttributeData, + $swatchHelper, + $swatchMediaHelper, + $data, + $swatchAttributesProvider + ); + $this->localeFormat = $localeFormat ?: ObjectManager::getInstance()->get( + \Magento\Framework\Locale\Format::class + ); + $this->variationPrices = $variationPrices ?: ObjectManager::getInstance()->get( + \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices::class + ); + } + /** * @return string */ @@ -66,6 +144,28 @@ public function getJsonConfig() $this->unsetData('allow_products'); return parent::getJsonConfig(); } + + /** + * Composes configuration for js price format + * + * @return string + */ + public function getPriceFormatJson() + { + return $this->jsonEncoder->encode($this->localeFormat->getPriceFormat()); + } + + /** + * Composes configuration for js price + * + * @return string + */ + public function getPricesJson() + { + return $this->jsonEncoder->encode( + $this->variationPrices->getFormattedPrices($this->getProduct()->getPriceInfo()) + ); + } /** * Do not load images for Configurable product with swatches due to its loaded by request diff --git a/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php b/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php index 77369ad12fd9f..6b72422d05014 100644 --- a/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php @@ -9,6 +9,7 @@ /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyFields) */ class ConfigurableTest extends \PHPUnit\Framework\TestCase { @@ -57,6 +58,9 @@ class ConfigurableTest extends \PHPUnit\Framework\TestCase /** @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject */ private $urlBuilder; + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $variationPricesMock; + public function setUp() { $this->arrayUtils = $this->createMock(\Magento\Framework\Stdlib\ArrayUtils::class); @@ -75,6 +79,9 @@ public function setUp() $this->scopeConfig = $this->createMock(\Magento\Framework\App\Config\ScopeConfigInterface::class); $this->imageHelper = $this->createMock(\Magento\Catalog\Helper\Image::class); $this->urlBuilder = $this->createMock(\Magento\Framework\UrlInterface::class); + $this->variationPricesMock = $this->createMock( + \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices::class + ); $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->configurable = $objectManagerHelper->getObject( @@ -93,6 +100,7 @@ public function setUp() 'priceCurrency' => $this->priceCurrency, 'configurableAttributeData' => $this->configurableAttributeData, 'data' => [], + 'variationPrices' => $this->variationPricesMock ] ); } @@ -201,4 +209,30 @@ private function prepareGetJsonSwatchConfig() $this->helper->expects($this->any())->method('getAllowAttributes')->with($this->product) ->willReturn([$attribute1]); } + + public function testGetPricesJson() + { + $expectedPrices = [ + 'oldPrice' => [ + 'amount' => 10, + ], + 'basePrice' => [ + 'amount' => 15, + ], + 'finalPrice' => [ + 'amount' => 20, + ], + ]; + + $priceInfoMock = $this->createMock(\Magento\Framework\Pricing\PriceInfo\Base::class); + $this->configurable->setProduct($this->product); + $this->product->expects($this->once())->method('getPriceInfo')->willReturn($priceInfoMock); + $this->variationPricesMock->expects($this->once()) + ->method('getFormattedPrices') + ->with($priceInfoMock) + ->willReturn($expectedPrices); + + $this->jsonEncoder->expects($this->once())->method('encode')->with($expectedPrices); + $this->configurable->getPricesJson(); + } } diff --git a/app/code/Magento/Swatches/view/frontend/templates/product/listing/renderer.phtml b/app/code/Magento/Swatches/view/frontend/templates/product/listing/renderer.phtml index 7ecd6558ef6ea..e65345b38d9b2 100644 --- a/app/code/Magento/Swatches/view/frontend/templates/product/listing/renderer.phtml +++ b/app/code/Magento/Swatches/view/frontend/templates/product/listing/renderer.phtml @@ -4,37 +4,38 @@ * See COPYING.txt for license details. */ ?> - -
- + + \ No newline at end of file