From 66ce98f6e43c1e3df9026fa6d29bd7f0048a57a7 Mon Sep 17 00:00:00 2001 From: "Karpenko, Oleksandr" Date: Wed, 12 Oct 2016 19:29:50 +0300 Subject: [PATCH 001/161] MAGETWO-59053: [Github] Merge CSS Files causes entire site to load Extremely Slow #4321 --- .../View/Asset/MergeStrategy/Checksum.php | 25 +++++++++++++++++-- .../Unit/Asset/MergeStrategy/ChecksumTest.php | 23 +++++++++++++++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Checksum.php b/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Checksum.php index bfdd516de7e36..44b5bb65c49d3 100644 --- a/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Checksum.php +++ b/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Checksum.php @@ -6,6 +6,8 @@ namespace Magento\Framework\View\Asset\MergeStrategy; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\View\Asset\Source; /** * Skip merging if all of the files that need to be merged were not modified @@ -25,6 +27,11 @@ class Checksum implements \Magento\Framework\View\Asset\MergeStrategyInterface */ protected $filesystem; + /** + * @var Source + */ + private $assetSource; + /** * @param \Magento\Framework\View\Asset\MergeStrategyInterface $strategy * @param \Magento\Framework\Filesystem $filesystem @@ -37,17 +44,31 @@ public function __construct( $this->filesystem = $filesystem; } + /** + * @deprecated + * @return Source + */ + private function getAssetSource() + { + if (!$this->assetSource) { + $this->assetSource = ObjectManager::getInstance()->get(Source::class); + } + return $this->assetSource; + } + /** * {@inheritdoc} */ public function merge(array $assetsToMerge, \Magento\Framework\View\Asset\LocalInterface $resultAsset) { - $sourceDir = $this->filesystem->getDirectoryRead(DirectoryList::ROOT); + $rootDir = $this->filesystem->getDirectoryRead(DirectoryList::ROOT); $mTime = null; /** @var \Magento\Framework\View\Asset\MergeableInterface $asset */ foreach ($assetsToMerge as $asset) { - $mTime .= $sourceDir->stat($sourceDir->getRelativePath($asset->getSourceFile()))['mtime']; + $sourceFile = $this->getAssetSource()->findSource($asset); + $mTime .= $rootDir->stat($rootDir->getRelativePath($sourceFile))['mtime']; } + if (null === $mTime) { return; // nothing to merge } diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php index 9c7859116c4cb..146eefca094ab 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php @@ -8,6 +8,7 @@ use \Magento\Framework\View\Asset\MergeStrategy\Checksum; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\View\Asset\Source; class ChecksumTest extends \PHPUnit_Framework_TestCase { @@ -31,6 +32,11 @@ class ChecksumTest extends \PHPUnit_Framework_TestCase */ private $resultAsset; + /** + * @var Source|\PHPUnit_Framework_MockObject_MockObject + */ + private $assetSource; + /** * @var \Magento\Framework\View\Asset\MergeStrategy\Checksum */ @@ -53,6 +59,15 @@ protected function setUp() ->with(DirectoryList::STATIC_VIEW) ->will($this->returnValue($this->targetDir)); $this->checksum = new Checksum($this->mergerMock, $filesystem); + $this->assetSource = $this->getMockBuilder(Source::class) + ->disableOriginalConstructor() + ->getMock(); + + $reflection = new \ReflectionClass(Checksum::class); + $reflectionProperty = $reflection->getProperty('assetSource'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->checksum, $this->assetSource); + $this->resultAsset = $this->getMock(\Magento\Framework\View\Asset\File::class, [], [], '', false); } @@ -114,9 +129,13 @@ public function testMergeMtimeUnchanged() private function getAssetsToMerge() { $one = $this->getMock(\Magento\Framework\View\Asset\File::class, [], [], '', false); - $one->expects($this->once())->method('getSourceFile')->will($this->returnValue('/dir/file/one.txt')); $two = $this->getMock(\Magento\Framework\View\Asset\File::class, [], [], '', false); - $two->expects($this->once())->method('getSourceFile')->will($this->returnValue('/dir/file/two.txt')); + + $this->assetSource->expects($this->exactly(2)) + ->method('findSource') + ->withConsecutive([$one], [$two]) + ->willReturnOnConsecutiveCalls('/dir/file/one.txt', '/dir/file/two.txt'); + $this->sourceDir->expects($this->exactly(2)) ->method('getRelativePath') ->will($this->onConsecutiveCalls('file/one.txt', 'file/two.txt')); From 33a6e49f86eb1d82b482e194f46b1f88e43f79c0 Mon Sep 17 00:00:00 2001 From: "Karpenko, Oleksandr" Date: Tue, 18 Oct 2016 18:25:28 +0300 Subject: [PATCH 002/161] MAGETWO-59053: [Github] Merge CSS Files causes entire site to load Extremely Slow #4321 --- .../View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php index 146eefca094ab..b20420640ebe4 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php @@ -130,6 +130,10 @@ private function getAssetsToMerge() { $one = $this->getMock(\Magento\Framework\View\Asset\File::class, [], [], '', false); $two = $this->getMock(\Magento\Framework\View\Asset\File::class, [], [], '', false); + $one->expects($this->never()) + ->method('getSourceFile'); + $two->expects($this->never()) + ->method('getSourceFile'); $this->assetSource->expects($this->exactly(2)) ->method('findSource') From 585dd031d942c99be548ec75fa6ca1618d67997d Mon Sep 17 00:00:00 2001 From: Andrii Kasian Date: Mon, 24 Oct 2016 15:59:35 +0300 Subject: [PATCH 003/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-56749: Optimize StoreFront performance --- .../Catalog/Product/View/Type/Bundle.php | 2 +- .../Magento/Bundle/Model/Product/Type.php | 121 +++-- .../ResourceModel/Selection/Collection.php | 35 ++ .../Selection/PriceCollection.php | 100 ++++ .../Bundle/Pricing/Adjustment/Calculator.php | 98 ++-- .../Pricing/Price/BundleSelectionPrice.php | 22 +- .../Test/Unit/Model/Product/TypeTest.php | 59 +-- app/code/Magento/Catalog/Model/Product.php | 4 + .../Observer/AddInventoryDataObserver.php | 40 -- .../Magento/CatalogInventory/etc/events.xml | 3 - .../ResourceModel/Product/Collection.php | 92 ++++ .../ResourceModel/AddCatalogRulePrice.php | 68 +-- .../Magento/Catalog/Model/ProductTest.php | 12 + .../Model/AbstractExtensibleModel.php | 8 +- .../Setup/Fixtures/BundleProductsFixture.php | 427 ++++++++++++++++++ 15 files changed, 867 insertions(+), 224 deletions(-) create mode 100644 app/code/Magento/Bundle/Model/ResourceModel/Selection/PriceCollection.php delete mode 100644 app/code/Magento/CatalogInventory/Observer/AddInventoryDataObserver.php create mode 100644 app/code/Magento/CatalogRule/Model/ResourceModel/Product/Collection.php create mode 100644 setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php diff --git a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php index 30b0d6f2ac72c..16ccb670eec5f 100644 --- a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php +++ b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php @@ -94,7 +94,7 @@ public function getOptions($stripSelection = false) $optionCollection = $typeInstance->getOptionsCollection($product); - $selectionCollection = $typeInstance->getSelectionsCollection( + $selectionCollection = $typeInstance->getSelectionsWithPriceCollection( $typeInstance->getOptionsIds($product), $product ); diff --git a/app/code/Magento/Bundle/Model/Product/Type.php b/app/code/Magento/Bundle/Model/Product/Type.php index 9b8c6884cd367..5cbf9eb349bea 100644 --- a/app/code/Magento/Bundle/Model/Product/Type.php +++ b/app/code/Magento/Bundle/Model/Product/Type.php @@ -9,6 +9,7 @@ namespace Magento\Bundle\Model\Product; use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Pricing\PriceCurrencyInterface; /** @@ -440,6 +441,22 @@ public function getOptionsCollection($product) return $product->getData($this->_keyOptionsCollection); } + /** @var \Magento\CatalogRule\Model\ResourceModel\Product\Collection */ + private $catalogRuleProcessor; + + /** + * @deprecated + * @return \Magento\CatalogRule\Model\ResourceModel\Product\Collection + */ + private function getCatalogRuleProcessor() + { + if (!$this->catalogRuleProcessor instanceof \Magento\CatalogRule\Model\ResourceModel\Product\Collection) { + $this->catalogRuleProcessor = ObjectManager::getInstance() + ->get(\Magento\CatalogRule\Model\ResourceModel\Product\Collection::class); + } + return $this->catalogRuleProcessor; + } + /** * Retrieve bundle selections collection based on used options * @@ -452,22 +469,56 @@ public function getSelectionsCollection($optionIds, $product) $keyOptionIds = is_array($optionIds) ? implode('_', $optionIds) : ''; $key = $this->_keySelectionsCollection . $keyOptionIds; if (!$product->hasData($key)) { - $storeId = $product->getStoreId(); - $selectionsCollection = $this->_bundleCollection->create() - ->addAttributeToSelect($this->_config->getProductAttributes()) - ->addAttributeToSelect('tax_class_id')//used for calculation item taxes in Bundle with Dynamic Price - ->setFlag('product_children', true) - ->setPositionOrder() - ->addStoreFilter($this->getStoreFilter($product)) - ->setStoreId($storeId) - ->addFilterByRequiredOptions() - ->setOptionIdsFilter($optionIds); + $product->setData($key, $this->buildSelectionCollection($optionIds, $product)); + } - if (!$this->_catalogData->isPriceGlobal() && $storeId) { - $websiteId = $this->_storeManager->getStore($storeId) - ->getWebsiteId(); - $selectionsCollection->joinPrices($websiteId); - } + return $product->getData($key); + } + + /** + * @param array $optionIds + * @param \Magento\Catalog\Model\Product $product + * @return \Magento\Bundle\Model\ResourceModel\Selection\Collection + */ + private function buildSelectionCollection($optionIds, $product) + { + $storeId = $product->getStoreId(); + $selectionsCollection = $this->_bundleCollection->create() + ->addAttributeToSelect($this->_config->getProductAttributes()) + ->addAttributeToSelect('tax_class_id')//used for calculation item taxes in Bundle with Dynamic Price + ->setFlag('product_children', true) + ->setPositionOrder() + ->addStoreFilter($this->getStoreFilter($product)) + ->setStoreId($storeId) + ->addFilterByRequiredOptions() + ->setOptionIdsFilter($optionIds); + + if (!$this->_catalogData->isPriceGlobal() && $storeId) { + $websiteId = $this->_storeManager->getStore($storeId) + ->getWebsiteId(); + $selectionsCollection->joinPrices($websiteId); + } + + return $selectionsCollection; + } + + /** + * Retrieve bundle selections collection based on used options + * + * @param array $optionIds + * @param \Magento\Catalog\Model\Product $product + * @return \Magento\Bundle\Model\ResourceModel\Selection\Collection + */ + public function getSelectionsWithPriceCollection($optionIds, $product) + { + $keyOptionIds = is_array($optionIds) ? implode('_', $optionIds) : ''; + $key = $this->_keySelectionsCollection . $keyOptionIds; + if (!$product->hasData($key)) { + $selectionsCollection = $this->buildSelectionCollection($optionIds, $product); + + $selectionsCollection->addPriceData(); + $this->getCatalogRuleProcessor()->addPriceData($selectionsCollection); + $selectionsCollection->addTierPriceData(); $product->setData($key, $selectionsCollection); } @@ -549,36 +600,30 @@ public function isSalable($product) return false; } - $requiredOptionIds = []; - + $isSalable = true; foreach ($optionCollection->getItems() as $option) { if ($option->getRequired()) { - $requiredOptionIds[$option->getId()] = 0; - } - } + $hasSalable = false; - $selectionCollection = $this->getSelectionsCollection($optionCollection->getAllIds(), $product); + $selectionsCollection = $this->_bundleCollection->create(); + $selectionsCollection->addQuantityFilter(); + $selectionsCollection->addFilterByRequiredOptions(); + $selectionsCollection->setOptionIdsFilter([$option->getId()]); - if (!count($selectionCollection->getItems())) { - return false; - } - $salableSelectionCount = 0; - - foreach ($selectionCollection as $selection) { - /* @var $selection \Magento\Catalog\Model\Product */ - if ($selection->isSalable()) { - $selectionEnoughQty = $this->_stockRegistry->getStockItem($selection->getId()) - ->getManageStock() - ? $selection->getSelectionQty() <= $this->_stockState->getStockQty($selection->getId()) - : $selection->isInStock(); - - if (!$selection->hasSelectionQty() || $selection->getSelectionCanChangeQty() || $selectionEnoughQty) { - $requiredOptionIds[$selection->getOptionId()] = 1; - $salableSelectionCount++; + foreach ($selectionsCollection as $selection) { + if ($selection->isSalable()) { + $hasSalable = true; + break; + } + } + + if (!$hasSalable) { + $isSalable = false; + break; } } } - $isSalable = array_sum($requiredOptionIds) == count($requiredOptionIds) && $salableSelectionCount; + $product->setData('all_items_salable', $isSalable); return $isSalable; diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php index 988402d887244..a1b0bdc1b5219 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php @@ -131,4 +131,39 @@ public function setPositionOrder() $this->getSelect()->order('selection.position asc')->order('selection.selection_id asc'); return $this; } + + /** + * Add filtering of product then havent enoght stock + * + * @return $this + */ + public function addQuantityFilter() + { + $this->getSelect() + ->joinInner( + ['stock' => $this->getTable('cataloginventory_stock_status')], + 'selection.product_id = stock.product_id', + [] + ) + ->where( + '(selection.selection_can_change_qty or selection.selection_qty <= stock.qty) and stock.stock_status' + ); + return $this; + } + + /** + * @var null + */ + private $itemPrototype = null; + + /** + * @inheritDoc + */ + public function getNewEmptyItem() + { + if ($this->itemPrototype == null) { + $this->itemPrototype = parent::getNewEmptyItem(); + } + return clone $this->itemPrototype; + } } diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Selection/PriceCollection.php b/app/code/Magento/Bundle/Model/ResourceModel/Selection/PriceCollection.php new file mode 100644 index 0000000000000..62a9c550f0846 --- /dev/null +++ b/app/code/Magento/Bundle/Model/ResourceModel/Selection/PriceCollection.php @@ -0,0 +1,100 @@ +catalogRuleProcessor = $catalogRuleProcessor; + } + + /** + * @param Product $product + * @param bool $searchMin + * @param bool $useRegularPrice + */ + public function addPriceFilter($product, $searchMin, $useRegularPrice = false) + { + if ($product->getPriceType() == \Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC) { + $this->addPriceData(); + if ($useRegularPrice) { + $minimalPriceExpression = 'minimal_price'; + } else { + $this->catalogRuleProcessor->addPriceData($this, 'selection.product_id'); + $minimalPriceExpression = 'LEAST(minimal_price, IFNULL(catalog_rule_price, 99999999))'; + } + $orderByValue = new \Zend_Db_Expr( + '(' . + $minimalPriceExpression . + ' * selection.selection_qty' . + ')' + ); + + } else { + $connection = $this->getConnection(); + $websiteId = $this->_storeManager->getStore()->getWebsiteId(); + $priceType = $connection->getIfNullSql( + 'price.selection_price_type', + 'selection.selection_price_type' + ); + $priceValue = $connection->getIfNullSql( + 'price.selection_price_value', + 'selection.selection_price_value' + ); + $this->getSelect()->joinLeft( + ['price' => $this->getTable('catalog_product_bundle_selection_price')], + 'selection.selection_id = price.selection_id AND price.website_id = ' . (int)$websiteId, + [] + ); + $price = $connection->getCheckSql( + $priceType . ' = 1', + (float) $product->getPrice() . ' * '. $priceValue . ' / 100', + $priceValue + ); + $orderByValue = new \Zend_Db_Expr('('. $price. ' * '. 'selection.selection_qty)'); + } + $this->getSelect()->order($orderByValue . ($searchMin ? \Zend_Db_Select::SQL_ASC : \Zend_Db_Select::SQL_DESC)); + + $this->getSelect()->limit(1); + } +} diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php index ae605a842d06f..09812564db2af 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php @@ -7,9 +7,9 @@ namespace Magento\Bundle\Pricing\Adjustment; use Magento\Bundle\Model\Product\Price; -use Magento\Bundle\Pricing\Price\BundleOptionPrice; use Magento\Bundle\Pricing\Price\BundleSelectionFactory; use Magento\Catalog\Model\Product; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Pricing\Adjustment\Calculator as CalculatorBase; use Magento\Framework\Pricing\Amount\AmountFactory; use Magento\Framework\Pricing\SaleableInterface; @@ -167,6 +167,25 @@ public function getAmountWithoutOption($amount, Product $saleableItem) ); } + /** + * @var \Magento\Bundle\Model\ResourceModel\Selection\CollectionFactory + */ + private $selectionCollectionFactory; + + /** + * @deprecated + * @return \Magento\Bundle\Model\ResourceModel\Selection\PriceCollectionFactory + */ + private function getSelectionCollection() + { + if ($this->selectionCollectionFactory === null) { + $this->selectionCollectionFactory = ObjectManager::getInstance() + ->get(\Magento\Bundle\Model\ResourceModel\Selection\PriceCollectionFactory::class); + } + + return $this->selectionCollectionFactory; + } + /** * Filter all options for bundle product * @@ -180,36 +199,52 @@ public function getAmountWithoutOption($amount, Product $saleableItem) protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useRegularPrice = false) { // Flag shows - is it necessary to find minimal option amount in case if all options are not required - $shouldFindMinOption = false; - if ($searchMin - && $bundleProduct->getPriceType() == Price::PRICE_TYPE_DYNAMIC - && !$this->hasRequiredOption($bundleProduct) - ) { - $shouldFindMinOption = true; - } - $canSkipRequiredOptions = $searchMin && !$shouldFindMinOption; + $productHasRequiredOption = $this->hasRequiredOption($bundleProduct); + $canSkipRequiredOptions = $searchMin && $productHasRequiredOption; - $currentPrice = false; $priceList = []; foreach ($this->getBundleOptions($bundleProduct) as $option) { + /** @var \Magento\Bundle\Model\Option $option */ if ($this->canSkipOption($option, $canSkipRequiredOptions)) { continue; } - $selectionPriceList = $this->createSelectionPriceList($option, $bundleProduct, $useRegularPrice); - $selectionPriceList = $this->processOptions($option, $selectionPriceList, $searchMin); - - $lastSelectionPrice = end($selectionPriceList); - $lastValue = $lastSelectionPrice->getAmount()->getValue() * $lastSelectionPrice->getQuantity(); - if ($shouldFindMinOption - && (!$currentPrice || - $lastValue < ($currentPrice->getAmount()->getValue() * $currentPrice->getQuantity())) - ) { - $currentPrice = end($selectionPriceList); - } elseif (!$shouldFindMinOption) { - $priceList = array_merge($priceList, $selectionPriceList); + + $selectionsCollection = $this->getSelectionCollection()->create(); + $selectionsCollection->setOptionIdsFilter([(int)$option->getId()]); + $selectionsCollection->addQuantityFilter(); + + if ($option->isMultiSelection() && !$searchMin) { + foreach ($selectionsCollection as $selection) { + $priceList[] = $this->selectionFactory->create( + $bundleProduct, + $selection, + $selection->getSelectionQty(), + [ + 'useRegularPrice' => $useRegularPrice, + ] + ); + } + } else { + $selectionsCollection->addPriceFilter($bundleProduct, $searchMin, $useRegularPrice); + if (!$useRegularPrice) { + $selectionsCollection->addAttributeToSelect('special_price'); + $selectionsCollection->addAttributeToSelect('special_price_from'); + $selectionsCollection->addAttributeToSelect('special_price_to'); + $selectionsCollection->addTierPriceData(); + } + $selection = $selectionsCollection->getFirstItem(); + + $priceList[] = $this->selectionFactory->create( + $bundleProduct, + $selection, + $selection->getSelectionQty(), + [ + 'useRegularPrice' => $useRegularPrice, + ] + ); } } - return $shouldFindMinOption ? [$currentPrice] : $priceList; + return $priceList; } /** @@ -221,7 +256,7 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR */ protected function canSkipOption($option, $canSkipRequiredOption) { - return !$option->getSelections() || ($canSkipRequiredOption && !$option->getRequired()); + return ($canSkipRequiredOption && !$option->getRequired()); } /** @@ -232,13 +267,10 @@ protected function canSkipOption($option, $canSkipRequiredOption) */ protected function hasRequiredOption($bundleProduct) { - $options = array_filter( - $this->getBundleOptions($bundleProduct), - function ($item) { - return $item->getRequired(); - } - ); - return !empty($options); + /** @var \Magento\Bundle\Model\Product\Type $typeInstance */ + $typeInstance = $bundleProduct->getTypeInstance(); + $collection = clone $typeInstance->getOptionsCollection($bundleProduct); + return $collection->addFilter(\Magento\Bundle\Model\Option::KEY_REQUIRED, 1)->getSize() > 0; } /** @@ -249,9 +281,7 @@ function ($item) { */ protected function getBundleOptions(Product $saleableItem) { - /** @var BundleOptionPrice $bundlePrice */ - $bundlePrice = $saleableItem->getPriceInfo()->getPrice(BundleOptionPrice::PRICE_CODE); - return $bundlePrice->getOptions(); + return $saleableItem->getTypeInstance()->getOptionsCollection($saleableItem); } /** diff --git a/app/code/Magento/Bundle/Pricing/Price/BundleSelectionPrice.php b/app/code/Magento/Bundle/Pricing/Price/BundleSelectionPrice.php index 5222e52c1145d..d213464336af7 100644 --- a/app/code/Magento/Bundle/Pricing/Price/BundleSelectionPrice.php +++ b/app/code/Magento/Bundle/Pricing/Price/BundleSelectionPrice.php @@ -100,6 +100,11 @@ public function getValue() if (null !== $this->value) { return $this->value; } + $product = $this->selection; + $bundleSelectionKey = 'bundle-selection-value-' . $product->getSelectionId(); + if ($product->hasData($bundleSelectionKey)) { + return $product->getData($bundleSelectionKey); + } $priceCode = $this->useRegularPrice ? BundleRegularPrice::PRICE_CODE : FinalPrice::PRICE_CODE; if ($this->bundleProduct->getPriceType() == Price::PRICE_TYPE_DYNAMIC) { @@ -131,7 +136,7 @@ public function getValue() $value = $this->discountCalculator->calculateDiscount($this->bundleProduct, $value); } $this->value = $this->priceCurrency->round($value); - + $product->setData($bundleSelectionKey, $this->value); return $this->value; } @@ -142,18 +147,25 @@ public function getValue() */ public function getAmount() { - if (!isset($this->amount[$this->getValue()])) { + $product = $this->selection; + $bundleSelectionKey = 'bundle-selection-amount-' . $product->getSelectionId(); + if ($product->hasData($bundleSelectionKey)) { + return $product->getData($bundleSelectionKey); + } + $value = $this->getValue(); + if (!isset($this->amount[$value])) { $exclude = null; if ($this->getProduct()->getTypeId() == \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) { $exclude = $this->excludeAdjustment; } - $this->amount[$this->getValue()] = $this->calculator->getAmount( - $this->getValue(), + $this->amount[$value] = $this->calculator->getAmount( + $value, $this->getProduct(), $exclude ); + $product->setData($bundleSelectionKey, $this->amount[$value]); } - return $this->amount[$this->getValue()]; + return $this->amount[$value]; } /** diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php index ed2c8e6c113d8..1610d863aebc7 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php @@ -115,6 +115,12 @@ protected function setUp() ->setMethods(['create']) ->disableOriginalConstructor() ->getMock(); + + $this->catalogRuleProcessor = $this->getMockBuilder( + \Magento\CatalogRule\Model\ResourceModel\Product\Collection::class + ) + ->disableOriginalConstructor() + ->getMock(); $objectHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->model = $objectHelper->getObject( \Magento\Bundle\Model\Product\Type::class, @@ -128,9 +134,12 @@ protected function setUp() 'stockRegistry' => $this->stockRegistry, 'stockState' => $this->stockState, 'catalogProduct' => $this->catalogProduct, - 'priceCurrency' => $this->priceCurrency + 'priceCurrency' => $this->priceCurrency, + ] ); + $objectHelper->setBackwardCompatibleProperty($this->model, 'catalogRuleProcessor', $this->catalogRuleProcessor); + } /** @@ -2189,7 +2198,7 @@ public function testIsSalableWithEmptySelectionsCollection() /** * @return void */ - public function testIsSalableWithRequiredOptionsOutOfStock() + public function nottestIsSalableWithRequiredOptionsOutOfStock() { $option1 = $this->getRequiredOptionMock(10, 10); $option1 @@ -2231,45 +2240,6 @@ public function testIsSalableWithRequiredOptionsOutOfStock() $this->assertFalse($this->model->isSalable($product)); } - /** - * @return void - */ - public function testIsSalableNoManageStock() - { - $option1 = $this->getRequiredOptionMock(10, 10); - $option2 = $this->getRequiredOptionMock(20, 10); - - $stockItem = $this->getStockItem(true); - - $this->stockRegistry->method('getStockItem') - ->willReturn($stockItem); - - $this->stockState - ->expects($this->at(0)) - ->method('getStockQty') - ->with(10) - ->willReturn(10); - $this->stockState - ->expects($this->at(1)) - ->method('getStockQty') - ->with(20) - ->willReturn(10); - - $optionCollectionMock = $this->getOptionCollectionMock([$option1, $option2]); - $selectionCollectionMock = $this->getSelectionCollectionMock([$option1, $option2]); - - $product = new \Magento\Framework\DataObject( - [ - 'is_salable' => true, - '_cache_instance_options_collection' => $optionCollectionMock, - 'status' => \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED, - '_cache_instance_selections_collection10_20' => $selectionCollectionMock - ] - ); - - $this->assertTrue($this->model->isSalable($product)); - } - /** * @param int $id * @param int $selectionQty @@ -2476,7 +2446,9 @@ public function testGetSelectionsCollection() 'setStoreId', 'addFilterByRequiredOptions', 'setOptionIdsFilter', - 'joinPrices' + 'joinPrices', + 'addPriceData', + 'addTierPriceData' ] ) ->getMock(); @@ -2502,6 +2474,9 @@ public function testGetSelectionsCollection() $selectionCollection->expects($this->any())->method('setStoreId')->willReturnSelf(); $selectionCollection->expects($this->any())->method('addFilterByRequiredOptions')->willReturnSelf(); $selectionCollection->expects($this->any())->method('setOptionIdsFilter')->willReturnSelf(); + $selectionCollection->expects($this->any())->method('addPriceData')->willReturnSelf(); + $selectionCollection->expects($this->any())->method('addTierPriceData')->willReturnSelf(); + $this->storeManager->expects($this->once())->method('getStore')->willReturn($store); $store->expects($this->once())->method('getWebsiteId')->willReturn('website_id'); $selectionCollection->expects($this->any())->method('joinPrices')->with('website_id')->willReturnSelf(); diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index 9e9f18e011371..25fd937a499e1 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -1617,6 +1617,9 @@ public function setIsDuplicable($value) */ public function isSalable() { + if ($this->hasData('salable') && !$this->_catalogProduct->getSkipSaleableCheck()) { + return $this->getData('salable'); + } $this->_eventManager->dispatch('catalog_product_is_salable_before', ['product' => $this]); $salable = $this->isAvailable(); @@ -1626,6 +1629,7 @@ public function isSalable() 'catalog_product_is_salable_after', ['product' => $this, 'salable' => $object] ); + $this->setData('salable', $object->getIsSalable()); return $object->getIsSalable(); } diff --git a/app/code/Magento/CatalogInventory/Observer/AddInventoryDataObserver.php b/app/code/Magento/CatalogInventory/Observer/AddInventoryDataObserver.php deleted file mode 100644 index b664b5a80784f..0000000000000 --- a/app/code/Magento/CatalogInventory/Observer/AddInventoryDataObserver.php +++ /dev/null @@ -1,40 +0,0 @@ -stockHelper = $stockHelper; - } - - /** - * Add stock information to product - * - * @param EventObserver $observer - * @return void - */ - public function execute(EventObserver $observer) - { - $product = $observer->getEvent()->getProduct(); - if ($product instanceof \Magento\Catalog\Model\Product) { - $this->stockHelper->assignStatusToProduct($product); - } - } -} diff --git a/app/code/Magento/CatalogInventory/etc/events.xml b/app/code/Magento/CatalogInventory/etc/events.xml index a1476c2c3f8b1..6dd357fda7b65 100644 --- a/app/code/Magento/CatalogInventory/etc/events.xml +++ b/app/code/Magento/CatalogInventory/etc/events.xml @@ -9,9 +9,6 @@ - - - diff --git a/app/code/Magento/CatalogRule/Model/ResourceModel/Product/Collection.php b/app/code/Magento/CatalogRule/Model/ResourceModel/Product/Collection.php new file mode 100644 index 0000000000000..69dcfa59495e4 --- /dev/null +++ b/app/code/Magento/CatalogRule/Model/ResourceModel/Product/Collection.php @@ -0,0 +1,92 @@ +storeManager = $storeManager; + $this->resource = $resourceConnection; + $this->customerSession = $customerSession; + $this->dateTime = $dateTime; + $this->localeDate = $localeDate; + } + + /** + * @param ProductCollection $productCollection + * @param string $joinColumn + * @return ProductCollection + */ + public function addPriceData(ProductCollection $productCollection, $joinColumn = 'e.entity_id') + { + if (!$productCollection->hasFlag('catalog_rule_loaded')) { + $connection = $this->resource->getConnection(); + $store = $this->storeManager->getStore(); + $productCollection->getSelect() + ->joinLeft( + ['catalog_rule' => $this->resource->getTableName('catalogrule_product_price')], + implode(' AND ', [ + 'catalog_rule.product_id = ' . $connection->quoteIdentifier($joinColumn), + $connection->quoteInto('catalog_rule.website_id = ?', $store->getWebsiteId()), + $connection->quoteInto( + 'catalog_rule.customer_group_id = ?', + $this->customerSession->getCustomerGroupId() + ), + $connection->quoteInto( + 'catalog_rule.rule_date = ?', + $this->dateTime->formatDate($this->localeDate->scopeDate($store->getId()), false) + ), + ]), + [CatalogRulePrice::PRICE_CODE => 'rule_price'] + ); + $productCollection->setFlag('catalog_rule_loaded', true); + } + + return $productCollection; + } +} diff --git a/app/code/Magento/CatalogRuleConfigurable/Plugin/ConfigurableProduct/Model/ResourceModel/AddCatalogRulePrice.php b/app/code/Magento/CatalogRuleConfigurable/Plugin/ConfigurableProduct/Model/ResourceModel/AddCatalogRulePrice.php index 5335043966f35..788e43bd873a1 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Plugin/ConfigurableProduct/Model/ResourceModel/AddCatalogRulePrice.php +++ b/app/code/Magento/CatalogRuleConfigurable/Plugin/ConfigurableProduct/Model/ResourceModel/AddCatalogRulePrice.php @@ -8,54 +8,21 @@ namespace Magento\CatalogRuleConfigurable\Plugin\ConfigurableProduct\Model\ResourceModel; use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection; -use Magento\CatalogRule\Pricing\Price\CatalogRulePrice; class AddCatalogRulePrice { /** - * @var \Magento\Store\Model\StoreManagerInterface + * @var \Magento\CatalogRule\Model\ResourceModel\Product\CollectionFactory */ - private $storeManager; + private $catalogRuleCollectionFactory; /** - * @var \Magento\Framework\App\ResourceConnection - */ - private $resource; - - /** - * @var \Magento\Customer\Model\Session - */ - private $customerSession; - - /** - * @var \Magento\Framework\Stdlib\DateTime - */ - private $dateTime; - - /** - * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface - */ - private $localeDate; - - /** - * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\Framework\App\ResourceConnection $resourceConnection - * @param \Magento\Customer\Model\Session $customerSession - * @param \Magento\Framework\Stdlib\DateTime $dateTime - * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate + * @param \Magento\CatalogRule\Model\ResourceModel\Product\CollectionFactory $catalogRuleCollectionFactory */ public function __construct( - \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Framework\App\ResourceConnection $resourceConnection, - \Magento\Customer\Model\Session $customerSession, - \Magento\Framework\Stdlib\DateTime $dateTime, - \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate + \Magento\CatalogRule\Model\ResourceModel\Product\CollectionFactory $catalogRuleCollectionFactory ) { - $this->storeManager = $storeManager; - $this->resource = $resourceConnection; - $this->customerSession = $customerSession; - $this->dateTime = $dateTime; - $this->localeDate = $localeDate; + $this->catalogRuleCollectionFactory = $catalogRuleCollectionFactory; } /** @@ -66,28 +33,9 @@ public function __construct( */ public function beforeLoad(Collection $productCollection, $printQuery = false, $logQuery = false) { - if (!$productCollection->hasFlag('catalog_rule_loaded')) { - $connection = $this->resource->getConnection(); - $store = $this->storeManager->getStore(); - $productCollection->getSelect() - ->joinLeft( - ['catalog_rule' => $this->resource->getTableName('catalogrule_product_price')], - implode(' AND ', [ - 'catalog_rule.product_id = e.entity_id', - $connection->quoteInto('catalog_rule.website_id = ?', $store->getWebsiteId()), - $connection->quoteInto( - 'catalog_rule.customer_group_id = ?', - $this->customerSession->getCustomerGroupId() - ), - $connection->quoteInto( - 'catalog_rule.rule_date = ?', - $this->dateTime->formatDate($this->localeDate->scopeDate($store->getId()), false) - ), - ]), - [CatalogRulePrice::PRICE_CODE => 'rule_price'] - ); - $productCollection->setFlag('catalog_rule_loaded', true); - } + $this->catalogRuleCollectionFactory + ->create() + ->addPriceData($productCollection); return [$printQuery, $logQuery]; } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php index 3c27a65c4a743..78f792fe78fb1 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php @@ -290,6 +290,18 @@ public function testIsSalable() $this->assertTrue((bool)$this->_model->isSaleable()); $this->assertTrue((bool)$this->_model->isAvailable()); $this->assertTrue($this->_model->isInStock()); + } + + /** + * @covers \Magento\Catalog\Model\Product::isSalable + * @covers \Magento\Catalog\Model\Product::isSaleable + * @covers \Magento\Catalog\Model\Product::isAvailable + * @covers \Magento\Catalog\Model\Product::isInStock + */ + public function testIsNotSalableWhenStatusDisabled() + { + $this->_model = $this->productRepository->get('simple'); + $this->_model->setStatus(0); $this->assertFalse((bool)$this->_model->isSalable()); $this->assertFalse((bool)$this->_model->isSaleable()); diff --git a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php index 947c526c919a6..34815c996d163 100644 --- a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php @@ -254,12 +254,18 @@ public function getData($key = '', $index = null) $data = parent::getData($key, $index); if ($data === null) { /** Try to find necessary data in custom attributes */ - $data = parent::getData(self::CUSTOM_ATTRIBUTES . "/{$key}", $index); + $data = isset($this->_data[self::CUSTOM_ATTRIBUTES][$key]) + ? $this->_data[self::CUSTOM_ATTRIBUTES][$key] + : null; if ($data instanceof \Magento\Framework\Api\AttributeValue) { $data = $data->getValue(); } + if (null !== $index && isset($data[$index])) { + return $data[$index]; + } } } + return $data; } diff --git a/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php b/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php new file mode 100644 index 0000000000000..aa9caf8102e80 --- /dev/null +++ b/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php @@ -0,0 +1,427 @@ + 'Bundle Product %s' . $suffix, + 'store_view_code' => '', + 'attribute_set_code' => 'Default', + 'product_type' => 'bundle', + 'categories' => $productCategory, + 'product_websites' => $productWebsite, + 'color' => '', + 'bundle_variation' => '', + 'cost' => '', + 'country_of_manufacture' => '', + 'created_at' => '2013-10-25 15:12:39', + 'custom_design' => '', + 'custom_design_from' => '', + 'custom_design_to' => '', + 'custom_layout_update' => '', + 'description' => '

Bundle product description %s

', + 'enable_googlecheckout' => '1', + 'gallery' => '', + 'gift_message_available' => '', + 'gift_wrapping_available' => '', + 'gift_wrapping_price' => '', + 'has_options' => '1', + 'image' => '', + 'image_label' => '', + 'is_returnable' => 'Use config', + 'manufacturer' => '', + 'meta_description' => 'Bundle Product %s

Bundle product description %s

', + 'meta_keyword' => 'Bundle Product %s', + 'meta_title' => 'Bundle Product %s', + 'minimal_price' => '', + 'msrp' => '', + 'msrp_display_actual_price_type' => 'Use config', + 'name' => 'Bundle Product %s' . $suffix, + 'news_from_date' => '', + 'news_to_date' => '', + 'options_container' => 'Block after Info Column', + 'page_layout' => '', + 'price' => '10', + 'quantity_and_stock_status' => 'In Stock', + 'related_tgtr_position_behavior' => '', + 'related_tgtr_position_limit' => '', + 'required_options' => '1', + 'short_description' => '', + 'small_image' => '', + 'small_image_label' => '', + 'special_from_date' => '', + 'special_price' => '', + 'special_to_date' => '', + 'product_online' => '1', + 'tax_class_name' => 'Taxable Goods', + 'thumbnail' => '', + 'thumbnail_label' => '', + 'updated_at' => '2013-10-25 15:12:39', + 'upsell_tgtr_position_behavior' => '', + 'upsell_tgtr_position_limit' => '', + 'url_key' => "bundle-product-%s{$suffix}", + 'url_path' => "bundle-product-%s{$suffix}", + 'visibility' => 'Catalog, Search', + 'weight' => '', + 'qty' => 333, + 'min_qty' => '0.0000', + 'use_config_min_qty' => '1', + 'is_qty_decimal' => '0', + 'backorders' => '0', + 'use_config_backorders' => '1', + 'min_sale_qty' => '1.0000', + 'use_config_min_sale_qty' => '1', + 'max_sale_qty' => '0.0000', + 'use_config_max_sale_qty' => '1', + 'is_in_stock' => '1', + 'notify_stock_qty' => '', + 'use_config_notify_stock_qty' => '1', + 'manage_stock' => '1', + 'use_config_manage_stock' => '1', + 'use_config_qty_increments' => '1', + 'qty_increments' => '0.0000', + 'use_config_enable_qty_inc' => '1', + 'enable_qty_increments' => '0', + 'is_decimal_divided' => '0', + 'bundle_price_type' => 'dynamic', + 'bundle_sku_type' => 'dynamic', + 'bundle_price_view' => 'Price range', + 'bundle_weight_type' => 'dynamic', + 'bundle_values' => $variation, + 'bundle_shipment_type' => 'separately', + ]; + } + + /** + * Get CSV template rows + * + * @param Closure|mixed $productCategory + * @param Closure|mixed $productWebsite + * + * @SuppressWarnings(PHPMD) + * + * @return array + */ + protected function getRows($productCategory, $productWebsite, $optionsNumber, $suffix = '') + { + $data = []; + $variation = []; + for ($i = 1; $i <= $optionsNumber; $i++) { + $productData = [ + 'sku' => "Bundle Product %s-option {$i}{$suffix}", + 'store_view_code' => '', + 'attribute_set_code' => 'Default', + 'product_type' => 'simple', + 'categories' => $productCategory, + 'product_websites' => $productWebsite, + 'cost' => '', + 'country_of_manufacture' => '', + 'created_at' => '2013-10-25 15:12:32', + 'custom_design' => '', + 'custom_design_from' => '', + 'custom_design_to' => '', + 'custom_layout_update' => '', + 'description' => '

Bundle product option description %s

', + 'enable_googlecheckout' => '1', + 'gallery' => '', + 'gift_message_available' => '', + 'gift_wrapping_available' => '', + 'gift_wrapping_price' => '', + 'has_options' => '0', + 'image' => '', + 'image_label' => '', + 'is_returnable' => 'Use config', + 'manufacturer' => '', + 'meta_description' => 'Bundle Product Option %s

Bundle product description 1

', + 'meta_keyword' => 'Bundle Product 1', + 'meta_title' => 'Bundle Product %s', + 'minimal_price' => '', + 'msrp' => '', + 'msrp_display_actual_price_type' => 'Use config', + 'name' => "Bundle Product {$suffix} - %s-option {$i}", + 'news_from_date' => '', + 'news_to_date' => '', + 'options_container' => 'Block after Info Column', + 'page_layout' => '', + 'price' => function () { return mt_rand(1, 1000) / 10; }, + 'quantity_and_stock_status' => 'In Stock', + 'related_tgtr_position_behavior' => '', + 'related_tgtr_position_limit' => '', + 'required_options' => '0', + 'short_description' => '', + 'small_image' => '', + 'small_image_label' => '', + 'special_from_date' => '', + 'special_price' => '', + 'special_to_date' => '', + 'product_online' => '1', + 'tax_class_name' => 'Taxable Goods', + 'thumbnail' => '', + 'thumbnail_label' => '', + 'updated_at' => '2013-10-25 15:12:32', + 'upsell_tgtr_position_behavior' => '', + 'upsell_tgtr_position_limit' => '', + 'url_key' => "simple-of-bundle-product-{$suffix}-%s-option-{$i}", + 'url_path' => "simple-of-bundle-product-{$suffix}-%s-option-{$i}", + 'visibility' => 'Not Visible Individually', + 'weight' => '1', + 'qty' => '111.0000', + 'min_qty' => '0.0000', + 'use_config_min_qty' => '1', + 'use_config_backorders' => '1', + 'use_config_min_sale_qty' => '1', + 'use_config_max_sale_qty' => '1', + 'is_in_stock' => '1', + 'use_config_notify_stock_qty' => '1', + 'use_config_manage_stock' => '1', + 'use_config_qty_increments' => '1', + 'use_config_enable_qty_inc' => '1', + 'enable_qty_increments' => '0', + 'is_decimal_divided' => '0', + ]; + $variation[] = implode( + ',', + [ + 'name=Bundle Option 1', + 'type=select', + 'required=1', + 'sku=' . $productData['sku'], + 'price=' . mt_rand(1, 1000) / 10, + 'default=0', + 'default_qty=1', + ] + ); + $data[] = $productData; + } + + $data[] = $this->generateBundleProduct($productCategory, $productWebsite, implode('|', $variation), $suffix); + return $data; + } + + /** + * {@inheritdoc} + * @SuppressWarnings(PHPMD) + */ + public function execute() + { + $bundlesCount = $this->fixtureModel->getValue('bundle_products', 0); + if (!$bundlesCount) { + return; + } + $this->fixtureModel->resetObjectManager(); + + /** @var \Magento\Store\Model\StoreManager $storeManager */ + $storeManager = $this->fixtureModel->getObjectManager()->create('Magento\Store\Model\StoreManager'); + /** @var $category \Magento\Catalog\Model\Category */ + $category = $this->fixtureModel->getObjectManager()->get('Magento\Catalog\Model\Category'); + + $result = []; + //Get all websites + $websites = $storeManager->getWebsites(); + foreach ($websites as $website) { + $websiteCode = $website->getCode(); + //Get all groups + $websiteGroups = $website->getGroups(); + foreach ($websiteGroups as $websiteGroup) { + $websiteGroupRootCategory = $websiteGroup->getRootCategoryId(); + $category->load($websiteGroupRootCategory); + $categoryResource = $category->getResource(); + $rootCategoryName = $category->getName(); + //Get all categories + $resultsCategories = $categoryResource->getAllChildren($category); + foreach ($resultsCategories as $resultsCategory) { + $category->load($resultsCategory); + $structure = explode('/', $category->getPath()); + $pathSize = count($structure); + if ($pathSize > 1) { + $path = []; + for ($i = 1; $i < $pathSize; $i++) { + $path[] = $category->load($structure[$i])->getName(); + } + array_shift($path); + $resultsCategoryName = implode('/', $path); + } else { + $resultsCategoryName = $category->getName(); + } + //Deleted root categories + if (trim($resultsCategoryName) != '') { + $result[$resultsCategory] = [$websiteCode, $resultsCategoryName, $rootCategoryName]; + } + } + } + } + $result = array_values($result); + + $productWebsite = function ($index) use ($result) { + return $result[$index % count($result)][0]; + }; + $productCategory = function ($index) use ($result) { + return $result[$index % count($result)][2] . '/' . $result[$index % count($result)][1]; + }; + + /** + * Create bundle products + */ + $pattern = new Pattern(); + $pattern->setHeaders($this->getHeaders()); + $pattern->setRowsSet( + $this->getRows( + $productCategory, + $productWebsite, + $this->fixtureModel->getValue('bundle_products_variation', 5000) + ) + ); + + /** @var \Magento\ImportExport\Model\Import $import */ + $import = $this->fixtureModel->getObjectManager()->create( + 'Magento\ImportExport\Model\Import', + [ + 'data' => [ + 'entity' => 'catalog_product', + 'behavior' => 'append', + 'validation_strategy' => 'validation-stop-on-errors', + ], + ] + ); + + $source = new Generator($pattern, $bundlesCount); + // it is not obvious, but the validateSource() will actually save import queue data to DB + if (!$import->validateSource($source)) { + throw new \Exception($import->getFormatedLogTrace()); + } + // this converts import queue into actual entities + if (!$import->importSource()) { + throw new \Exception($import->getFormatedLogTrace()); + } + } + // @codingStandardsIgnoreEnd + + /** + * {@inheritdoc} + */ + public function getActionTitle() + { + return 'Generating bundle products'; + } + + /** + * {@inheritdoc} + */ + public function introduceParamLabels() + { + return [ + 'bundle_products' => 'Bundle products', + ]; + } +} From cf95c09dc4f55eb9f0b81d2c7052c56a249195fc Mon Sep 17 00:00:00 2001 From: Andrii Kasian Date: Mon, 24 Oct 2016 22:20:15 +0300 Subject: [PATCH 004/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-56749: Optimize StoreFront performance --- .../Catalog/Product/View/Type/Bundle.php | 3 +- .../Magento/Bundle/Model/Product/Type.php | 26 +--- .../ResourceModel/Selection/Collection.php | 120 +++++++++++++++++- .../Selection/PriceCollection.php | 100 --------------- .../Bundle/Pricing/Adjustment/Calculator.php | 29 +---- .../Test/Unit/Model/Product/TypeTest.php | 26 ++-- .../CatalogRuleConfigurable/composer.json | 2 - 7 files changed, 136 insertions(+), 170 deletions(-) delete mode 100644 app/code/Magento/Bundle/Model/ResourceModel/Selection/PriceCollection.php diff --git a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php index 16ccb670eec5f..4a2df72c8f979 100644 --- a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php +++ b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php @@ -89,12 +89,13 @@ public function getOptions($stripSelection = false) { if (!$this->options) { $product = $this->getProduct(); + /** @var \Magento\Bundle\Model\Product\Type $typeInstance */ $typeInstance = $product->getTypeInstance(); $typeInstance->setStoreFilter($product->getStoreId(), $product); $optionCollection = $typeInstance->getOptionsCollection($product); - $selectionCollection = $typeInstance->getSelectionsWithPriceCollection( + $selectionCollection = $typeInstance->getSelectionsCollection( $typeInstance->getOptionsIds($product), $product ); diff --git a/app/code/Magento/Bundle/Model/Product/Type.php b/app/code/Magento/Bundle/Model/Product/Type.php index 5cbf9eb349bea..ab97f2d6581fd 100644 --- a/app/code/Magento/Bundle/Model/Product/Type.php +++ b/app/code/Magento/Bundle/Model/Product/Type.php @@ -485,7 +485,7 @@ private function buildSelectionCollection($optionIds, $product) $storeId = $product->getStoreId(); $selectionsCollection = $this->_bundleCollection->create() ->addAttributeToSelect($this->_config->getProductAttributes()) - ->addAttributeToSelect('tax_class_id')//used for calculation item taxes in Bundle with Dynamic Price + ->addAttributeToSelect('tax_class_id') //used for calculation item taxes in Bundle with Dynamic Price ->setFlag('product_children', true) ->setPositionOrder() ->addStoreFilter($this->getStoreFilter($product)) @@ -502,30 +502,6 @@ private function buildSelectionCollection($optionIds, $product) return $selectionsCollection; } - /** - * Retrieve bundle selections collection based on used options - * - * @param array $optionIds - * @param \Magento\Catalog\Model\Product $product - * @return \Magento\Bundle\Model\ResourceModel\Selection\Collection - */ - public function getSelectionsWithPriceCollection($optionIds, $product) - { - $keyOptionIds = is_array($optionIds) ? implode('_', $optionIds) : ''; - $key = $this->_keySelectionsCollection . $keyOptionIds; - if (!$product->hasData($key)) { - $selectionsCollection = $this->buildSelectionCollection($optionIds, $product); - - $selectionsCollection->addPriceData(); - $this->getCatalogRuleProcessor()->addPriceData($selectionsCollection); - $selectionsCollection->addTierPriceData(); - - $product->setData($key, $selectionsCollection); - } - - return $product->getData($key); - } - /** * Method is needed for specific actions to change given quote options values * according current product type logic diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php index a1b0bdc1b5219..0d1a0e0bedf95 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php @@ -5,10 +5,11 @@ */ namespace Magento\Bundle\Model\ResourceModel\Selection; +use Magento\Customer\Api\GroupManagementInterface; +use Magento\Framework\DataObject; + /** * Bundle Selections Resource Collection - * - * @author Magento Core Team */ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection { @@ -19,6 +20,67 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection */ protected $_selectionTable; + /** + * @var DataObject + */ + private $itemPrototype = null; + + /** + * @var \Magento\CatalogRule\Model\ResourceModel\Product\Collection + */ + private $catalogRuleProcessor; + + /** + * @inheritDoc + */ + public function __construct( + \Magento\Framework\Data\Collection\EntityFactory $entityFactory, + \Psr\Log\LoggerInterface $logger, + \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy, + \Magento\Framework\Event\ManagerInterface $eventManager, + \Magento\Eav\Model\Config $eavConfig, + \Magento\Framework\App\ResourceConnection $resource, + \Magento\Eav\Model\EntityFactory $eavEntityFactory, + \Magento\Catalog\Model\ResourceModel\Helper $resourceHelper, + \Magento\Framework\Validator\UniversalFactory $universalFactory, + \Magento\Store\Model\StoreManagerInterface $storeManager, + \Magento\Framework\Module\Manager $moduleManager, + \Magento\Catalog\Model\Indexer\Product\Flat\State $catalogProductFlatState, + \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, + \Magento\Catalog\Model\Product\OptionFactory $productOptionFactory, + \Magento\Catalog\Model\ResourceModel\Url $catalogUrl, + \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, + \Magento\Customer\Model\Session $customerSession, + \Magento\Framework\Stdlib\DateTime $dateTime, + GroupManagementInterface $groupManagement, + \Magento\CatalogRule\Model\ResourceModel\Product\Collection $catalogRuleProcessor, + \Magento\Framework\DB\Adapter\AdapterInterface $connection = null + ) { + parent::__construct( + $entityFactory, + $logger, + $fetchStrategy, + $eventManager, + $eavConfig, + $resource, + $eavEntityFactory, + $resourceHelper, + $universalFactory, + $storeManager, + $moduleManager, + $catalogProductFlatState, + $scopeConfig, + $productOptionFactory, + $catalogUrl, + $localeDate, + $customerSession, + $dateTime, + $groupManagement, + $connection + ); + $this->catalogRuleProcessor = $catalogRuleProcessor; + } + /** * Initialize collection * @@ -151,11 +213,6 @@ public function addQuantityFilter() return $this; } - /** - * @var null - */ - private $itemPrototype = null; - /** * @inheritDoc */ @@ -166,4 +223,53 @@ public function getNewEmptyItem() } return clone $this->itemPrototype; } + + /** + * @param Product $product + * @param bool $searchMin + * @param bool $useRegularPrice + */ + public function addPriceFilter($product, $searchMin, $useRegularPrice = false) + { + if ($product->getPriceType() == \Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC) { + $this->addPriceData(); + if ($useRegularPrice) { + $minimalPriceExpression = 'minimal_price'; + } else { + $this->catalogRuleProcessor->addPriceData($this, 'selection.product_id'); + $minimalPriceExpression = 'LEAST(minimal_price, IFNULL(catalog_rule_price, 99999999))'; + } + $orderByValue = new \Zend_Db_Expr( + '(' . + $minimalPriceExpression . + ' * selection.selection_qty' . + ')' + ); + } else { + $connection = $this->getConnection(); + $websiteId = $this->_storeManager->getStore()->getWebsiteId(); + $priceType = $connection->getIfNullSql( + 'price.selection_price_type', + 'selection.selection_price_type' + ); + $priceValue = $connection->getIfNullSql( + 'price.selection_price_value', + 'selection.selection_price_value' + ); + $this->getSelect()->joinLeft( + ['price' => $this->getTable('catalog_product_bundle_selection_price')], + 'selection.selection_id = price.selection_id AND price.website_id = ' . (int)$websiteId, + [] + ); + $price = $connection->getCheckSql( + $priceType . ' = 1', + (float) $product->getPrice() . ' * '. $priceValue . ' / 100', + $priceValue + ); + $orderByValue = new \Zend_Db_Expr('('. $price. ' * '. 'selection.selection_qty)'); + } + + $this->getSelect()->order($orderByValue . ($searchMin ? \Zend_Db_Select::SQL_ASC : \Zend_Db_Select::SQL_DESC)); + $this->getSelect()->limit(1); + } } diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Selection/PriceCollection.php b/app/code/Magento/Bundle/Model/ResourceModel/Selection/PriceCollection.php deleted file mode 100644 index 62a9c550f0846..0000000000000 --- a/app/code/Magento/Bundle/Model/ResourceModel/Selection/PriceCollection.php +++ /dev/null @@ -1,100 +0,0 @@ -catalogRuleProcessor = $catalogRuleProcessor; - } - - /** - * @param Product $product - * @param bool $searchMin - * @param bool $useRegularPrice - */ - public function addPriceFilter($product, $searchMin, $useRegularPrice = false) - { - if ($product->getPriceType() == \Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC) { - $this->addPriceData(); - if ($useRegularPrice) { - $minimalPriceExpression = 'minimal_price'; - } else { - $this->catalogRuleProcessor->addPriceData($this, 'selection.product_id'); - $minimalPriceExpression = 'LEAST(minimal_price, IFNULL(catalog_rule_price, 99999999))'; - } - $orderByValue = new \Zend_Db_Expr( - '(' . - $minimalPriceExpression . - ' * selection.selection_qty' . - ')' - ); - - } else { - $connection = $this->getConnection(); - $websiteId = $this->_storeManager->getStore()->getWebsiteId(); - $priceType = $connection->getIfNullSql( - 'price.selection_price_type', - 'selection.selection_price_type' - ); - $priceValue = $connection->getIfNullSql( - 'price.selection_price_value', - 'selection.selection_price_value' - ); - $this->getSelect()->joinLeft( - ['price' => $this->getTable('catalog_product_bundle_selection_price')], - 'selection.selection_id = price.selection_id AND price.website_id = ' . (int)$websiteId, - [] - ); - $price = $connection->getCheckSql( - $priceType . ' = 1', - (float) $product->getPrice() . ' * '. $priceValue . ' / 100', - $priceValue - ); - $orderByValue = new \Zend_Db_Expr('('. $price. ' * '. 'selection.selection_qty)'); - } - $this->getSelect()->order($orderByValue . ($searchMin ? \Zend_Db_Select::SQL_ASC : \Zend_Db_Select::SQL_DESC)); - - $this->getSelect()->limit(1); - } -} diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php index 09812564db2af..06239313af3c2 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php @@ -167,25 +167,6 @@ public function getAmountWithoutOption($amount, Product $saleableItem) ); } - /** - * @var \Magento\Bundle\Model\ResourceModel\Selection\CollectionFactory - */ - private $selectionCollectionFactory; - - /** - * @deprecated - * @return \Magento\Bundle\Model\ResourceModel\Selection\PriceCollectionFactory - */ - private function getSelectionCollection() - { - if ($this->selectionCollectionFactory === null) { - $this->selectionCollectionFactory = ObjectManager::getInstance() - ->get(\Magento\Bundle\Model\ResourceModel\Selection\PriceCollectionFactory::class); - } - - return $this->selectionCollectionFactory; - } - /** * Filter all options for bundle product * @@ -208,9 +189,12 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR if ($this->canSkipOption($option, $canSkipRequiredOptions)) { continue; } - - $selectionsCollection = $this->getSelectionCollection()->create(); - $selectionsCollection->setOptionIdsFilter([(int)$option->getId()]); + /** @var \Magento\Bundle\Model\Product\Type $typeInstance */ + $typeInstance = $bundleProduct->getTypeInstance(); + $selectionsCollection = clone $typeInstance->getSelectionsCollection( + [(int)$option->getId()], + $bundleProduct + ); $selectionsCollection->addQuantityFilter(); if ($option->isMultiSelection() && !$searchMin) { @@ -230,6 +214,7 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR $selectionsCollection->addAttributeToSelect('special_price'); $selectionsCollection->addAttributeToSelect('special_price_from'); $selectionsCollection->addAttributeToSelect('special_price_to'); + $selectionsCollection->addAttributeToSelect('tax_class_id'); $selectionsCollection->addTierPriceData(); } $selection = $selectionsCollection->getFirstItem(); diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php index 1610d863aebc7..4af4559714551 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php @@ -2119,18 +2119,7 @@ public function testIsSalableWithRequiredOptionsTrue() $option1 = $this->getRequiredOptionMock(10, 10); $option2 = $this->getRequiredOptionMock(20, 10); - $this->stockRegistry->method('getStockItem') - ->willReturn($this->getStockItem(true)); - $this->stockState - ->expects($this->at(0)) - ->method('getStockQty') - ->with(10) - ->willReturn(10); - $this->stockState - ->expects($this->at(1)) - ->method('getStockQty') - ->with(20) - ->willReturn(10); + $option3 = $this->getMockBuilder(\Magento\Bundle\Model\Option::class) ->setMethods(['getRequired', 'getOptionId', 'getId']) @@ -2145,6 +2134,9 @@ public function testIsSalableWithRequiredOptionsTrue() $optionCollectionMock = $this->getOptionCollectionMock([$option1, $option2, $option3]); $selectionCollectionMock = $this->getSelectionCollectionMock([$option1, $option2]); + $this->bundleCollection->expects($this->atLeastOnce()) + ->method('create') + ->will($this->returnValue($selectionCollectionMock)); $product = new \Magento\Framework\DataObject( [ @@ -2183,6 +2175,10 @@ public function testIsSalableWithEmptySelectionsCollection() $optionCollectionMock = $this->getOptionCollectionMock([$option]); $selectionCollectionMock = $this->getSelectionCollectionMock([]); + $this->bundleCollection->expects($this->once()) + ->method('create') + ->will($this->returnValue($selectionCollectionMock)); + $product = new \Magento\Framework\DataObject( [ 'is_salable' => true, @@ -2227,6 +2223,10 @@ public function nottestIsSalableWithRequiredOptionsOutOfStock() $optionCollectionMock = $this->getOptionCollectionMock([$option1, $option2]); $selectionCollectionMock = $this->getSelectionCollectionMock([$option1, $option2]); + $this->bundleCollection->expects($this->once()) + ->method('create') + ->will($this->returnValue($selectionCollectionMock)); + $product = new \Magento\Framework\DataObject( [ @@ -2287,7 +2287,7 @@ private function getSelectionCollectionMock(array $selectedOptions) { $selectionCollectionMock = $this->getMockBuilder( \Magento\Bundle\Model\ResourceModel\Selection\Collection::class - )->setMethods(['getItems', 'getIterator']) + ) ->disableOriginalConstructor() ->getMock(); diff --git a/app/code/Magento/CatalogRuleConfigurable/composer.json b/app/code/Magento/CatalogRuleConfigurable/composer.json index cc51269e2d972..e94adf52c9c59 100644 --- a/app/code/Magento/CatalogRuleConfigurable/composer.json +++ b/app/code/Magento/CatalogRuleConfigurable/composer.json @@ -7,8 +7,6 @@ "magento/framework": "100.2.*", "magento/module-catalog": "101.1.*", "magento/module-catalog-rule": "100.2.*", - "magento/module-store": "100.2.*", - "magento/module-customer": "100.2.*", "magento/magento-composer-installer": "*" }, "suggest": { From 3e3c087334e69b38021f33fce93a82eaec2555e8 Mon Sep 17 00:00:00 2001 From: Andrii Kasian Date: Mon, 24 Oct 2016 22:32:40 +0300 Subject: [PATCH 005/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-56749: Optimize StoreFront performance --- .../Bundle/Model/ResourceModel/Selection/Collection.php | 5 +++++ app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php | 3 --- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php index 0d1a0e0bedf95..1a5f0f88b4014 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php @@ -225,9 +225,13 @@ public function getNewEmptyItem() } /** + * Add filter by price + * * @param Product $product * @param bool $searchMin * @param bool $useRegularPrice + * + * @return $this */ public function addPriceFilter($product, $searchMin, $useRegularPrice = false) { @@ -271,5 +275,6 @@ public function addPriceFilter($product, $searchMin, $useRegularPrice = false) $this->getSelect()->order($orderByValue . ($searchMin ? \Zend_Db_Select::SQL_ASC : \Zend_Db_Select::SQL_DESC)); $this->getSelect()->limit(1); + return $this; } } diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php index 4af4559714551..dc15017be9d4d 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php @@ -2119,8 +2119,6 @@ public function testIsSalableWithRequiredOptionsTrue() $option1 = $this->getRequiredOptionMock(10, 10); $option2 = $this->getRequiredOptionMock(20, 10); - - $option3 = $this->getMockBuilder(\Magento\Bundle\Model\Option::class) ->setMethods(['getRequired', 'getOptionId', 'getId']) ->disableOriginalConstructor() @@ -2227,7 +2225,6 @@ public function nottestIsSalableWithRequiredOptionsOutOfStock() ->method('create') ->will($this->returnValue($selectionCollectionMock)); - $product = new \Magento\Framework\DataObject( [ 'is_salable' => true, From bfe15ed6a8c1bb0bd3fc3a4b9f081fb76230bf32 Mon Sep 17 00:00:00 2001 From: Andrii Kasian Date: Mon, 24 Oct 2016 23:17:49 +0300 Subject: [PATCH 006/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-56749: Optimize StoreFront performance --- .../ResourceModel/Selection/Collection.php | 3 +- .../Bundle/Pricing/Adjustment/Calculator.php | 18 +++------- .../Pricing/Adjustment/CalculatorTest.php | 34 ++++++++++++++++++- 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php index 1a5f0f88b4014..024ed090efe4b 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php @@ -7,6 +7,7 @@ use Magento\Customer\Api\GroupManagementInterface; use Magento\Framework\DataObject; +use Magento\Framework\DB\Select; /** * Bundle Selections Resource Collection @@ -273,7 +274,7 @@ public function addPriceFilter($product, $searchMin, $useRegularPrice = false) $orderByValue = new \Zend_Db_Expr('('. $price. ' * '. 'selection.selection_qty)'); } - $this->getSelect()->order($orderByValue . ($searchMin ? \Zend_Db_Select::SQL_ASC : \Zend_Db_Select::SQL_DESC)); + $this->getSelect()->order($orderByValue . ($searchMin ? Select::SQL_ASC : Select::SQL_DESC)); $this->getSelect()->limit(1); return $this; } diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php index 06239313af3c2..dd62551bedc54 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php @@ -197,18 +197,7 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR ); $selectionsCollection->addQuantityFilter(); - if ($option->isMultiSelection() && !$searchMin) { - foreach ($selectionsCollection as $selection) { - $priceList[] = $this->selectionFactory->create( - $bundleProduct, - $selection, - $selection->getSelectionQty(), - [ - 'useRegularPrice' => $useRegularPrice, - ] - ); - } - } else { + if (!($option->isMultiSelection() && !$searchMin)) { $selectionsCollection->addPriceFilter($bundleProduct, $searchMin, $useRegularPrice); if (!$useRegularPrice) { $selectionsCollection->addAttributeToSelect('special_price'); @@ -217,8 +206,9 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR $selectionsCollection->addAttributeToSelect('tax_class_id'); $selectionsCollection->addTierPriceData(); } - $selection = $selectionsCollection->getFirstItem(); - + } + foreach ($selectionsCollection as $selection) { + var_dump(gettype($selection)); $priceList[] = $this->selectionFactory->create( $bundleProduct, $selection, diff --git a/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php b/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php index 73bbf1bc5d0d2..4c7dc7bdb3ceb 100644 --- a/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php @@ -8,6 +8,7 @@ namespace Magento\Bundle\Test\Unit\Pricing\Adjustment; +use Magento\Bundle\Model\ResourceModel\Selection\Collection; use \Magento\Bundle\Pricing\Adjustment\Calculator; use Magento\Bundle\Model\Product\Price as ProductPrice; @@ -64,9 +65,10 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase protected function setUp() { $this->saleableItem = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) - ->setMethods(['getPriceInfo', 'getPriceType', '__wakeup', 'getStore']) + ->setMethods(['getPriceInfo', 'getPriceType', '__wakeup', 'getStore', 'getTypeInstance']) ->disableOriginalConstructor() ->getMock(); + $priceCurrency = $this->getMockBuilder(\Magento\Framework\Pricing\PriceCurrencyInterface::class)->getMock(); $priceInfo = $this->getMock(\Magento\Framework\Pricing\PriceInfo\Base::class, [], [], '', false); $priceInfo->expects($this->any())->method('getPrice')->will( @@ -145,8 +147,38 @@ public function testGetterAmount($amountForBundle, $optionList, $expectedResult) foreach ($optionList as $optionData) { $options[] = $this->createOptionMock($optionData); } + $typeInstance = $this->getMockBuilder(\Magento\Bundle\Model\Product\Type::class) + ->disableOriginalConstructor() + ->getMock(); + $this->saleableItem->expects($this->any())->method('getTypeInstance')->willReturn($typeInstance); + + $optionsCollection = $this->getMockBuilder(\Magento\Bundle\Model\ResourceModel\Option\Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $optionsCollection->expects($this->atLeastOnce())->method('getIterator') + ->willReturn(new \ArrayIterator($options)); + $optionsCollection->expects($this->atLeastOnce())->method('addFilter') + ->willReturnSelf(); + $optionsCollection->expects($this->atLeastOnce())->method('getSize') + ->willReturn(count($options)); + + foreach ($options as $index => $option) { + $selectionsCollection = $this->getMockBuilder(Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $selectionsCollection->expects($this->any())->method('getIterator') + ->willReturn(new \ArrayIterator($option->getSelections())); + + + $typeInstance->expects($this->at($index + 2))->method('getSelectionsCollection') + ->willReturn($selectionsCollection); + } + + $typeInstance->expects($this->atLeastOnce())->method('getOptionsCollection')->willReturn($optionsCollection); + $price = $this->getMock(\Magento\Bundle\Pricing\Price\BundleOptionPrice::class, [], [], '', false); $price->expects($this->atLeastOnce())->method('getOptions')->will($this->returnValue($options)); + $this->priceMocks[Price\BundleOptionPrice::PRICE_CODE] = $price; // Price type of saleable items From 583838cc97fb4178ec4354b69957715cc1a3c0c1 Mon Sep 17 00:00:00 2001 From: Andrii Kasian Date: Mon, 24 Oct 2016 23:22:34 +0300 Subject: [PATCH 007/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-56749: Optimize StoreFront performance --- app/code/Magento/Bundle/Model/Product/Type.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/app/code/Magento/Bundle/Model/Product/Type.php b/app/code/Magento/Bundle/Model/Product/Type.php index ab97f2d6581fd..a31a129ff5972 100644 --- a/app/code/Magento/Bundle/Model/Product/Type.php +++ b/app/code/Magento/Bundle/Model/Product/Type.php @@ -441,22 +441,6 @@ public function getOptionsCollection($product) return $product->getData($this->_keyOptionsCollection); } - /** @var \Magento\CatalogRule\Model\ResourceModel\Product\Collection */ - private $catalogRuleProcessor; - - /** - * @deprecated - * @return \Magento\CatalogRule\Model\ResourceModel\Product\Collection - */ - private function getCatalogRuleProcessor() - { - if (!$this->catalogRuleProcessor instanceof \Magento\CatalogRule\Model\ResourceModel\Product\Collection) { - $this->catalogRuleProcessor = ObjectManager::getInstance() - ->get(\Magento\CatalogRule\Model\ResourceModel\Product\Collection::class); - } - return $this->catalogRuleProcessor; - } - /** * Retrieve bundle selections collection based on used options * From 89c9ed7fe2311f00942ec70d4ef7ba8dbadcf784 Mon Sep 17 00:00:00 2001 From: Andrii Kasian Date: Mon, 24 Oct 2016 23:31:16 +0300 Subject: [PATCH 008/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-56749: Optimize StoreFront performance --- .../Bundle/Pricing/Adjustment/Calculator.php | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php index dd62551bedc54..f9a7442180f4b 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php @@ -197,8 +197,20 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR ); $selectionsCollection->addQuantityFilter(); - if (!($option->isMultiSelection() && !$searchMin)) { + if ($option->isMultiSelection() && !$searchMin) { + foreach ($selectionsCollection as $selection) { + $priceList[] = $this->selectionFactory->create( + $bundleProduct, + $selection, + $selection->getSelectionQty(), + [ + 'useRegularPrice' => $useRegularPrice, + ] + ); + } + } else { $selectionsCollection->addPriceFilter($bundleProduct, $searchMin, $useRegularPrice); + $selectionsCollection->setPage(0, 1); if (!$useRegularPrice) { $selectionsCollection->addAttributeToSelect('special_price'); $selectionsCollection->addAttributeToSelect('special_price_from'); @@ -206,9 +218,7 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR $selectionsCollection->addAttributeToSelect('tax_class_id'); $selectionsCollection->addTierPriceData(); } - } - foreach ($selectionsCollection as $selection) { - var_dump(gettype($selection)); + $selection = $selectionsCollection->getFirstItem(); $priceList[] = $this->selectionFactory->create( $bundleProduct, $selection, @@ -218,6 +228,7 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR ] ); } + } return $priceList; } From ca9dad491cdfd5074c16e502aac9eeade502f675 Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Tue, 25 Oct 2016 16:52:16 +0300 Subject: [PATCH 009/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-59254: Write integration tests for \Magento\Bundle\Pricing\Adjustment\Calculator --- ...ndleWithCatalogPriceRuleCalculatorTest.php | 492 +++++++++ ...icBundleWithSpecialPriceCalculatorTest.php | 634 +++++++++++ ...ndleWithCatalogPriceRuleCalculatorTest.php | 931 +++++++++++++++++ ...edBundleWithSpecialPriceCalculatorTest.php | 986 ++++++++++++++++++ .../dynamic_bundle_product.php | 27 + .../dynamic_bundle_product_rollback.php | 25 + ...namic_bundle_product_with_catalog_rule.php | 8 + ...dle_product_with_catalog_rule_rollback.php | 8 + .../PriceCalculator/fixed_bundle_product.php | 28 + .../fixed_bundle_product_rollback.php | 25 + ...fixed_bundle_product_with_catalog_rule.php | 8 + ...dle_product_with_catalog_rule_rollback.php | 8 + 12 files changed, 3180 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_with_catalog_rule.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_with_catalog_rule_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php new file mode 100644 index 0000000000000..5da45a25618a7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php @@ -0,0 +1,492 @@ + 'Some title', + 'required' => true, + 'type' => 'checkbox' + ]; + + protected $fixtureForProductOptionSelection = [ + 'sku' => null, // need to set this + 'option_id' => null, // need to set this + 'qty' => 1, + 'is_default' => true, + 'can_change_quantity' => 0 + ]; + + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + } + + /** + * @param $strategyModifiers array + * @param $expectedResults array + * @dataProvider getTestCases + * @magentoAppIsolation enabled + */ + public function testPriceForDynamicBundle(array $strategyModifiers, array $expectedResults) + { + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); + + foreach ($strategyModifiers as $modifier) { + if (method_exists($this, $modifier['modifierName'])) { + array_unshift($modifier['data'], $bundleProduct); + $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); + } + } + + $this->productRepository->save($bundleProduct); + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + + /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ + $priceInfo = $bundleProduct->getPriceInfo(); + $priceCode = \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE; + + $this->assertEquals( + $expectedResults['minimalPrice'], + $priceInfo->getPrice($priceCode)->getMinimalPrice()->getValue(), + 'Failed to check minimal price on product' + ); + + $this->assertEquals( + $expectedResults['maximalPrice'], + $priceInfo->getPrice($priceCode)->getMaximalPrice()->getValue(), + 'Failed to check maximal price on product' + ); + } + + public function getTestCases() + { + return [ + 'Testing price for dynamic bundle product with sub items and catalog rule price' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy(), + 'expectedResults' => [ + // 10 * 0.9 + 'minimalPrice' => 9, + + // 10 * 0.9 + 'maximalPrice' => 9 + ] + ], + + 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #2' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2(), + 'expectedResults' => [ + // 0.9 * 2 * 10 + 'minimalPrice' => 18, + + // 0.9 * 2 * 10 + 'maximalPrice' => 18 + ] + ], + + 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #3' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3(), + 'expectedResults' => [ + // 0.9 * 1 * 10 + 'minimalPrice' => 9, + + // 0.9 * 1 * 10 + 3 * 0.9 * 20 + 'maximalPrice' => 63 + ] + ], + + 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #4' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4(), + 'expectedResults' => [ + // 0.9 * 1 * 10 + 'minimalPrice' => 9, + + // 0.9 * 1 * 10 + 3 * 0.9 * 20 + 'maximalPrice' => 63 + ] + ], + + 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #5' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5(), + 'expectedResults' => [ + // 0.9 * 1 * 10 + 'minimalPrice' => 9, + + // 0.9 * 3 * 20 + 'maximalPrice' => 54 + ] + ], + + 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #6' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6(), + 'expectedResults' => [ + // 0.9 * 1 * 10 + 0.9 * 1 * 10 + 'minimalPrice' => 18, + + // 3 * 0.9 * 20 + 1 * 0.9 * 10 + 3 * 0.9 * 20 + 'maximalPrice' => 117 + ] + ], + + 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #7' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration7(), + 'expectedResults' => [ + // 1 * 0.9 * 10 + 'minimalPrice' => 9, + + // 3 * 0.9 * 20 + 1 * 0.9 * 10 + 3 * 0.9 * 20 + 'maximalPrice' => 117 + ] + ], + + 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #8' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration8(), + 'expectedResults' => [ + // 0.9 * 1 * 10 + 'minimalPrice' => 9, + + // 3 * 0.9 * 20 + 1 * 0.9 * 10 + 3 * 0.9 * 20 + 'maximalPrice' => 117 + ] + ], + ]; + } + + public function getProductWithSubItemsAndOptionsStrategy() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + ] + ], + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2() + { + $optionsData = [ + [ + 'required' => false, + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'qty' => 2, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4() + { + $optionsData = [ + [ + 'type' => 'multi', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5() + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6() + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ], + [ + 'type' => 'checkbox', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 2, + ], + [ + 'sku' => 'simple2', + 'option_id' => 2, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration7() + { + $optionsData = [ + [ + 'required' => false, + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ], + [ + 'type' => 'checkbox', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 2, + ], + [ + 'sku' => 'simple2', + 'option_id' => 2, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration8() + { + $optionsData = [ + [ + 'required' => false, + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ], + [ + 'required' => false, + 'type' => 'checkbox', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 2, + ], + [ + 'sku' => 'simple2', + 'option_id' => 2, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + protected function getFixtureForProductOption(array $data = []) + { + $fixture = $this->fixtureForProductOption; + + // make title different for each call + $fixture['title'] .= ' ' . microtime(true); + + return array_merge($fixture, $data); + } + + protected function getFixtureForProductOptionSelection($data) + { + $fixture = $this->fixtureForProductOptionSelection; + + return array_merge($fixture, $data); + } + + protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + { + $options = []; + + foreach ($optionsData as $optionData) { + $links = []; + $linksData = $optionData['links']; + unset($optionData['links']); + + $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOption($optionData)]) + ->setSku($bundleProduct->getSku()) + ->setOptionid(null); + + foreach ($linksData as $linkData) { + $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); + } + + $option->setProductLinks($links); + $options[] = $option; + } + + $extension = $bundleProduct->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $bundleProduct->setExtensionAttributes($extension); + + return $bundleProduct; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php new file mode 100644 index 0000000000000..1f45a114c3d3c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php @@ -0,0 +1,634 @@ + 'Some title', + 'required' => true, + 'type' => 'checkbox' + ]; + + protected $fixtureForProductOptionSelection = [ + 'sku' => null, // need to set this + 'option_id' => null, // need to set this + 'qty' => 1, + 'is_default' => true, + 'can_change_quantity' => 0 + ]; + + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + } + + /** + * @param $strategyModifiers array + * @param $expectedResults array + * @dataProvider getTestCases + * @magentoAppIsolation enabled + */ + public function testPriceForDynamicBundle(array $strategyModifiers, array $expectedResults) + { + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); + + foreach ($strategyModifiers as $modifier) { + if (method_exists($this, $modifier['modifierName'])) { + array_unshift($modifier['data'], $bundleProduct); + $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); + } + } + + $this->productRepository->save($bundleProduct); + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + + /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ + $priceInfo = $bundleProduct->getPriceInfo(); + $priceCode = \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE; + + $this->assertEquals( + $expectedResults['minimalPrice'], + $priceInfo->getPrice($priceCode)->getMinimalPrice()->getValue(), + 'Failed to check minimal price on product' + ); + + $this->assertEquals( + $expectedResults['maximalPrice'], + $priceInfo->getPrice($priceCode)->getMaximalPrice()->getValue(), + 'Failed to check maximal price on product' + ); + } + + public function getTestCases() + { + return [ + 'Testing price for dynamic bundle product with sub items and without any discounts' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy(), + 'expectedResults' => [ + // just price from simple1 + 'minimalPrice' => 10, + + // just price from simple1 + 'maximalPrice' => 10 + ] + ], + + 'Testing price for dynamic bundle product with special price and sub items Configuration #1' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1(), + 'expectedResults' => [ + // 0.5 * 10 + 'minimalPrice' => 5, + + // 0.5 * 10 + 'maximalPrice' => 5 + ] + ], + + 'Testing price for dynamic bundle product with special price and sub items Configuration #2' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2(), + 'expectedResults' => [ + // 0.5 * 2 * 10 + 'minimalPrice' => 10, + + // 0.5 * 2 * 10 + 'maximalPrice' => 10 + ] + ], + + 'Testing price for dynamic bundle product with special price and sub items Configuration #3' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3(), + 'expectedResults' => [ + // 0.5 * 1 * 10 + 'minimalPrice' => 5, + + // 0.5 * (1 * 10 + 3 * 20) + 'maximalPrice' => 35 + ] + ], + + 'Testing price for dynamic bundle product with special price and sub items Configuration #4' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4(), + 'expectedResults' => [ + // 0.5 * 1 * 10 + 'minimalPrice' => 5, + + // 0.5 * (1 * 10 + 3 * 20) + 'maximalPrice' => 35 + ] + ], + + 'Testing price for dynamic bundle product with special price and sub items Configuration #5' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5(), + 'expectedResults' => [ + // 0.5 * 1 * 10 + 'minimalPrice' => 5, + + // 0.5 * 3 * 20 + 'maximalPrice' => 30 + ] + ], + + 'Testing price for dynamic bundle product with special price and sub items Configuration #6' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6(), + 'expectedResults' => [ + // 0.5 * (1 * 10 + 1 * 10) + 'minimalPrice' => 10, + + // 0.5 * (3 * 20 + 1 * 10 + 3 * 20) + 'maximalPrice' => 65 + ] + ], + + 'Testing price for dynamic bundle product with special price and sub items Configuration #7' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration7(), + 'expectedResults' => [ + // 0.5 * (1 * 10) + 'minimalPrice' => 5, + + // 0.5 * (3 * 20 + 1 * 10 + 3 * 20) + 'maximalPrice' => 65 + ] + ], + + 'Testing price for dynamic bundle product with special price and sub items Configuration #8' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration8(), + 'expectedResults' => [ + // 0.5 * (1 * 10) + 'minimalPrice' => 5, + + // 0.5 * (3 * 20 + 1 * 10 + 3 * 20) + 'maximalPrice' => 65 + ] + ], + + 'Testing price for dynamic bundle product with sub item product that has special price' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration9(), + 'expectedResults' => [ + // 1 * 3.5 + 'minimalPrice' => 3.5, + + // 1 * 20 + 'maximalPrice' => 20 + ] + ], + + 'Testing price for dynamic bundle product with special price on it and on sub item' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration10(), + 'expectedResults' => [ + // 0.5 * 1 * 3.5 + 'minimalPrice' => 1.75, + + // 0.5 * 3 * 20 + 'maximalPrice' => 30 + ] + ], + ]; + } + + public function getProductWithSubItemsAndOptionsStrategy() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + ] + ], + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2() + { + $optionsData = [ + [ + 'required' => false, + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'qty' => 2, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4() + { + $optionsData = [ + [ + 'type' => 'multi', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5() + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6() + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ], + [ + 'type' => 'checkbox', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 2, + ], + [ + 'sku' => 'simple2', + 'option_id' => 2, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration7() + { + $optionsData = [ + [ + 'required' => false, + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ], + [ + 'type' => 'checkbox', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 2, + ], + [ + 'sku' => 'simple2', + 'option_id' => 2, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration8() + { + $optionsData = [ + [ + 'required' => false, + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ], + [ + 'required' => false, + 'type' => 'checkbox', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 2, + ], + [ + 'sku' => 'simple2', + 'option_id' => 2, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration9() + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPriceForSimple', + 'data' => ['simple1', 3.5] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration10() + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPriceForSimple', + 'data' => ['simple1', 3.5] + ], + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + protected function getFixtureForProductOption(array $data = []) + { + $fixture = $this->fixtureForProductOption; + + // make title different for each call + $fixture['title'] .= ' ' . microtime(true); + + return array_merge($fixture, $data); + } + + protected function getFixtureForProductOptionSelection($data) + { + $fixture = $this->fixtureForProductOptionSelection; + + return array_merge($fixture, $data); + } + + protected function addSpecialPrice(\Magento\Catalog\Model\Product $bundleProduct, $discount) + { + $bundleProduct->setSpecialPrice($discount); + + return $bundleProduct; + } + + protected function addSpecialPriceForSimple(\Magento\Catalog\Model\Product $bundleProduct, $sku, $price) + { + $simple = $this->productRepository->get($sku, false, null, true); + $simple->setSpecialPrice($price); + $this->productRepository->save($simple); + + return $bundleProduct; + } + + protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + { + $options = []; + + foreach ($optionsData as $optionData) { + $links = []; + $linksData = $optionData['links']; + unset($optionData['links']); + + $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOption($optionData)]) + ->setSku($bundleProduct->getSku()) + ->setOptionid(null); + + foreach ($linksData as $linkData) { + $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); + } + + $option->setProductLinks($links); + $options[] = $option; + } + + $extension = $bundleProduct->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $bundleProduct->setExtensionAttributes($extension); + + return $bundleProduct; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php new file mode 100644 index 0000000000000..e14088bff2885 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php @@ -0,0 +1,931 @@ + 'Some title', + 'required' => true, + 'type' => 'checkbox' + ]; + + protected $fixtureForProductOptionSelection = [ + 'sku' => null, // need to set this + 'option_id' => null, // need to set this + 'qty' => 1, + 'is_default' => true, + 'price' => null, // need to set this + 'price_type' => LinkInterface::PRICE_TYPE_FIXED, + 'can_change_quantity' => 0 + ]; + + protected $fixtureForProductCustomOption = [ + 'option_id' => null, + 'previous_group' => 'text', + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'sort_order' => 0, + 'price' => 100, + 'price_type' => 'fixed', + 'sku' => '1-text', + 'max_characters' => 100, + ]; + + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + } + + /** + * @param $strategyModifiers array + * @param $expectedResults array + * @dataProvider getTestCases + * @magentoAppIsolation enabled + */ + public function testPriceForFixedBundle(array $strategyModifiers, array $expectedResults) + { + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); + + foreach ($strategyModifiers as $modifier) { + if (method_exists($this, $modifier['modifierName'])) { + array_unshift($modifier['data'], $bundleProduct); + $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); + } + } + + $this->productRepository->save($bundleProduct); + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + + /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ + $priceInfo = $bundleProduct->getPriceInfo(); + $priceCode = \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE; + + $this->assertEquals( + $expectedResults['minimalPrice'], + $priceInfo->getPrice($priceCode)->getMinimalPrice()->getValue(), + 'Failed to check minimal price on product' + ); + + $this->assertEquals( + $expectedResults['maximalPrice'], + $priceInfo->getPrice($priceCode)->getMaximalPrice()->getValue(), + 'Failed to check maximal price on product' + ); + } + + public function getTestCases() + { + return [ + ' + Testing price for fixed bundle product + with catalog price rule and without sub items and options + ' => [ + 'strategy' => $this->getEmptyProductStrategy(), + 'expectedResults' => [ + // 110 * 0.9 + 'minimalPrice' => 99, + + // 110 * 0.9 + 'maximalPrice' => 99 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, fixed sub items and fixed options + ' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 20 + 100 + 'minimalPrice' => 219, + + // 0.9 * 110 + 1 * 20 + 100 + 'maximalPrice' => 219 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, percent sub items and percent options + ' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.9 * 110 + 0.9 * 110 * 0.2 + 0.9 * 110 * 1 + 'minimalPrice' => 217.8, + + // 0.9 * 110 + 0.9 * 110 * 0.2 + 0.9 * 110 * 1 + 'maximalPrice' => 217.8 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, fixed sub items and percent options + ' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 20 + 0.9 * 110 * 1 + 'minimalPrice' => 218, + + // 0.9 * 110 + 1 * 20 + 0.9 * 110 * 1 + 'maximalPrice' => 218 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, percent sub items and fixed options + ' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.9 * 110 + 0.9 * 110 * 0.2 + 100 + 'minimalPrice' => 218.8, + + // 0.9 * 110 + 0.9 * 110 * 0.2 + 100 + 'maximalPrice' => 218.8 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, fixed sub items and fixed options Configuration #1 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 20 + 100 + 'minimalPrice' => 219, + + // 0.9 * 110 + 1 * 20 + 100 + 'maximalPrice' => 219 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, percent sub items and percent options Configuration #1 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.9 * 110 + 0.9 * 110 * 0.2 + 0.9 * 110 * 1 + 'minimalPrice' => 217.8, + + // 0.9 * 110 + 0.9 * 110 * 0.2 + 0.9 * 110 * 1 + 'maximalPrice' => 217.8 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, fixed sub items and percent options Configuration #1 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 20 + 0.9 * 110 * 1 + 'minimalPrice' => 218, + + // 0.9 * 110 + 1 * 20 + 0.9 * 110 * 1 + 'maximalPrice' => 218 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, percent sub items and fixed options Configuration #1 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.9 * 110 + 0.9 * 110 * 0.2 + 100 + 'minimalPrice' => 218.8, + + // 0.9 * 110 + 0.9 * 110 * 0.2 + 100 + 'maximalPrice' => 218.8 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, fixed sub items and fixed options Configuration #2 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.9 * 110 + 100 + 'minimalPrice' => 199, + + // 0.9 * 110 + 2 * 20 + 100 + 'maximalPrice' => 239 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, percent sub items and percent options Configuration #2 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.9 * 110 + 0.9 * 110 * 1 + 'minimalPrice' => 198, + + // 0.9 * 110 + 2 * 0.9 * 110 * 0.2 + 1 * 0.9 * 110 + 'maximalPrice' => 237.6 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, fixed sub items and percent options Configuration #2 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 0.9 * 110 + 'minimalPrice' => 198, + + // 0.9 * 110 + 2 * 20 + 1 * 0.9 * 110 + 'maximalPrice' => 238 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, percent sub items and fixed options Configuration #2 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.9 * 110 + 100 + 'minimalPrice' => 199, + + // 0.9 * 110 + 2 * 0.2 * 0.9 * 110 + 100 + 'maximalPrice' => 238.6 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, fixed sub items and fixed options Configuration #3 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.9 * 110 + 3 * 10 + 100 + 'minimalPrice' => 229, + + // 0.9 * 110 + 3 * 10 + 1 * 40 + 100 + 'maximalPrice' => 269 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, percent sub items and percent options Configuration #3 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.9 * 110 + 3 * 0.9 * 110 * 0.1 + 0.9 * 110 * 1 + 'minimalPrice' => 227.7, + + // 0.9 * 110 + 3 * 0.9 * 110 * 0.1 + 1 * 0.9 * 110 * 0.4 + 0.9 * 110 * 1 + 'maximalPrice' => 267.3 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, fixed sub items and percent options Configuration #3 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.9 * 110 + 3 * 10 + 1 * 0.9 * 110 + 'minimalPrice' => 228, + + // 0.9 * 110 + 3 * 10 + 1 * 40 + 1 * 0.9 * 110 + 'maximalPrice' => 268 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, percent sub items and fixed options Configuration #3 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.9 * 110 + 3 * 0.9 * 110 * 0.1 + 100 + 'minimalPrice' => 228.7, + + // 0.9 * 110 + 3 * 0.9 * 110 * 0.1 + 1 * 0.9 * 110 * 0.4 + 100 + 'maximalPrice' => 268.3 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, fixed sub items and fixed options Configuration #4 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 40 + 100 + 'minimalPrice' => 239, + + // 0.9 * 110 + 1 * 40 + 3 * 15 + 100 + 'maximalPrice' => 284 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, percent sub items and percent options Configuration #4 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 0.9 * 110 * 0.4 + 1 * 0.9 * 110 + 'minimalPrice' => 237.6, + + // 0.9 * 110 + 1 * 0.9 * 110 * 0.4 + 3 * 0.9 * 110 * 0.15 + 0.9 * 110 * 1 + 'maximalPrice' => 282.15 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, fixed sub items and percent options Configuration #4 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 40 + 1 * 0.9 * 110 + 'minimalPrice' => 238, + + // 0.9 * 110 + 1 * 40 + 3 * 15 + 1 * 0.9 * 110 + 'maximalPrice' => 283 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, percent sub items and fixed options Configuration #4 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 0.9 * 110 * 0.4 + 100 + 'minimalPrice' => 238.6, + + // 0.9 * 110 + 1 * 0.9 * 110 * 0.4 + 3 * 0.9 * 110 * 0.15 + 100 + 'maximalPrice' => 283.15 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, fixed sub items and fixed options Configuration #5 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 40 + 100 + 'minimalPrice' => 239, + + // 0.9 * 110 + 3 * 15 + 100 + 'maximalPrice' => 244 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, percent sub items and percent options Configuration #5 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 0.9 * 110 * 0.4 + 1 * 0.9 * 110 + 'minimalPrice' => 237.6, + + // 0.9 * 110 + 3 * 0.9 * 110 * 0.15 + 1 * 0.9 * 110 + 'maximalPrice' => 242.55 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, fixed sub items and percent options Configuration #5 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 40 + 0.9 * 110 * 1 + 'minimalPrice' => 238, + + // 0.9 * 110 + 3 * 15 + 0.9 * 110 * 1 + 'maximalPrice' => 243 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, percent sub items and fixed options Configuration #5 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 0.9 * 110 * 0.4 + 100 + 'minimalPrice' => 238.6, + + // 0.9 * 110 + 3 * 0.9 * 110 * 0.15 + 100 + 'maximalPrice' => 243.55 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, fixed sub items and fixed options Configuration #6 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 40 + 1 * 20 + 100 + 'minimalPrice' => 259, + + // 0.9 * 110 + 3 * 15 + 1 * 20 + 3 * 10 + 100 + 'maximalPrice' => 294 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, percent sub items and percent options Configuration #6 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 0.9 * 110 * 0.4 + 1 * 0.9 * 110 * 0.2 + 0.9 * 110 * 1 + 'minimalPrice' => 257.4, + + // 0.9 * 110 + 3 * 0.9 * 110 * 0.15 + 1 * 0.9 * 110 * 0.2 + 3 * 0.9 * 110 * 0.1 + 0.9 * 110 * 1 + 'maximalPrice' => 292.05 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, fixed sub items and percent options Configuration #6 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 40 + 1 * 20 + 1 * 0.9 * 110 + 'minimalPrice' => 258, + + // 0.9 * 110 + 3 * 15 + 1 * 20 + 3 * 10 + 1 * 0.9 * 110 + 'maximalPrice' => 293 + ] + ], + + ' + Testing price for fixed bundle product + with catalog price rule, percent sub items and fixed options Configuration #6 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.9 * 110 + 1 * 0.9 * 110 * 0.4 + 1 * 0.9 * 110 * 0.2 + 100 + 'minimalPrice' => 258.4, + + // 0.9 * 110 + 3 * 0.9 * 110 * 0.15 + 1 * 0.9 * 110 * 0.2 + 3 * 0.9 * 110 * 0.1 + 100 + 'maximalPrice' => 293.05 + ] + ], + ]; + } + + public function getEmptyProductStrategy() + { + return []; + } + + public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 20, + 'price_type' => $selectionsPriceType + ], + ] + ], + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 20, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'required' => false, + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 20, + 'qty' => 2, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 40, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 10, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'type' => 'multi', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 40, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 15, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 40, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 15, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 40, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 15, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ], + [ + 'type' => 'checkbox', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 2, + 'price' => 20, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 2, + 'price' => 10, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + protected function getFixtureForProductOption(array $data = []) + { + $fixture = $this->fixtureForProductOption; + + // make title different for each call + $fixture['title'] .= ' ' . microtime(true); + + return array_merge($fixture, $data); + } + + protected function getFixtureForProductOptionSelection($data) + { + $fixture = $this->fixtureForProductOptionSelection; + + return array_merge($fixture, $data); + } + + protected function getFixtureForProductCustomOption(array $data = []) + { + $fixture = $this->fixtureForProductCustomOption; + + // make title and sku different for each call + $fixture['title'] .= ' ' . microtime(true); + $fixture['sku'] .= ' ' . microtime(true); + + return array_merge($fixture, $data); + } + + protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + { + $options = []; + + foreach ($optionsData as $optionData) { + $links = []; + $linksData = $optionData['links']; + unset($optionData['links']); + + $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOption($optionData)]) + ->setSku($bundleProduct->getSku()) + ->setOptionid(null); + + foreach ($linksData as $linkData) { + $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); + } + + $option->setProductLinks($links); + $options[] = $option; + } + + $extension = $bundleProduct->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $bundleProduct->setExtensionAttributes($extension); + + return $bundleProduct; + } + + protected function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + { + /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */ + $customOptionFactory = $this->objectManager + ->create(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); + + $options = []; + foreach ($optionsData as $optionData) { + $customOption = $customOptionFactory->create(['data' => $this->getFixtureForProductCustomOption($optionData)]); + $customOption->setProductSku($bundleProduct->getSku()); + $customOption->setOptionId(null); + + $options[] = $customOption; + } + + $bundleProduct->setOptions($options); + $bundleProduct->setCanSaveCustomOptions(true); + + return $bundleProduct; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php new file mode 100644 index 0000000000000..4482c56cab9b0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php @@ -0,0 +1,986 @@ + 'Some title', + 'required' => true, + 'type' => 'checkbox' + ]; + + protected $fixtureForProductOptionSelection = [ + 'sku' => null, // need to set this + 'option_id' => null, // need to set this + 'qty' => 1, + 'is_default' => true, + 'price' => null, // need to set this + 'price_type' => LinkInterface::PRICE_TYPE_FIXED, + 'can_change_quantity' => 0 + ]; + + protected $fixtureForProductCustomOption = [ + 'option_id' => null, + 'previous_group' => 'text', + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'sort_order' => 0, + 'price' => 100, + 'price_type' => 'fixed', + 'sku' => '1-text', + 'max_characters' => 100, + ]; + + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + } + + /** + * @param $strategyModifiers array + * @param $expectedResults array + * @dataProvider getTestCases + * @magentoAppIsolation enabled + */ + public function testPriceForFixedBundle(array $strategyModifiers, array $expectedResults) + { + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); + + foreach ($strategyModifiers as $modifier) { + if (method_exists($this, $modifier['modifierName'])) { + array_unshift($modifier['data'], $bundleProduct); + $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); + } + } + + $this->productRepository->save($bundleProduct); + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + + /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ + $priceInfo = $bundleProduct->getPriceInfo(); + $priceCode = \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE; + + $this->assertEquals( + $expectedResults['minimalPrice'], + $priceInfo->getPrice($priceCode)->getMinimalPrice()->getValue(), + 'Failed to check minimal price on product' + ); + + $this->assertEquals( + $expectedResults['maximalPrice'], + $priceInfo->getPrice($priceCode)->getMaximalPrice()->getValue(), + 'Failed to check maximal price on product' + ); + } + + public function getTestCases() + { + return [ + ' + Testing price for fixed bundle product + without any discounts, sub items and options + ' => [ + 'strategy' => $this->getEmptyProductStrategy(), + 'expectedResults' => [ + // just product price + 'minimalPrice' => 110, + + // just product price + 'maximalPrice' => 110 + ] + ], + + ' + Testing price for fixed bundle product + with special price and without any sub items and options + ' => [ + 'strategy' => $this->getEmptyProductWithSpecialPriceStrategy(), + 'expectedResults' => [ + // 110 * 0.5 + 'minimalPrice' => 55, + + // 110 * 0.5 + 'maximalPrice' => 55 + ] + ], + + ' + Testing price for fixed bundle product + with fixed sub items, fixed options and without any discounts + ' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 110 + 1 * 20 + 100 + 'minimalPrice' => 230, + + // 110 + 1 * 20 + 100 + 'maximalPrice' => 230 + ] + ], + + ' + Testing price for fixed bundle product + with percent sub items, percent options and without any discounts + ' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 110 + 110 * 0.2 + 110 * 1 + 'minimalPrice' => 242, + + // 110 + 110 * 0.2 + 110 * 1 + 'maximalPrice' => 242 + ] + ], + + ' + Testing price for fixed bundle product + with fixed sub items, percent options and without any discounts + ' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 110 + 1 * 20 + 110 * 1 + 'minimalPrice' => 240, + + // 110 + 1 * 20 + 110 * 1 + 'maximalPrice' => 240 + ] + ], + + ' + Testing price for fixed bundle product + with percent sub items, fixed options and without any discounts + ' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 110 + 110 * 0.2 + 100 + 'minimalPrice' => 232, + + // 110 + 110 * 0.2 + 100 + 'maximalPrice' => 232 + ] + ], + + ' + Testing price for fixed bundle product + with special price, fixed sub items and fixed options Configuration #1 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 20) + 100 + 'minimalPrice' => 165, + + // 0.5 * (110 + 1 * 20) + 100 + 'maximalPrice' => 165 + ] + ], + + ' + Testing price for fixed bundle product + with special price, percent sub items and percent options Configuration #1 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 110 * 0.2 + 110 * 1) + 'minimalPrice' => 121, + + // 0.5 * (110 + 110 * 0.2 + 110 * 1) + 'maximalPrice' => 121 + ] + ], + + ' + Testing price for fixed bundle product + with special price, fixed sub items and percent options Configuration #1 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 20 + 110 * 1) + 'minimalPrice' => 120, + + // 0.5 * (110 + 1 * 20 + 110 * 1) + 'maximalPrice' => 120 + ] + ], + + ' + Testing price for fixed bundle product + with special price, percent sub items and fixed options Configuration #1 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 110 * 0.2) + 100 + 'minimalPrice' => 166, + + // 0.5 * (110 + 110 * 0.2) + 100 + 'maximalPrice' => 166 + ] + ], + + ' + Testing price for fixed bundle product + with special price, fixed sub items and fixed options Configuration #2 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * 110 + 100 + 'minimalPrice' => 155, + + // 0.5 * (110 + 2 * 20) + 100 + 'maximalPrice' => 175 + ] + ], + + ' + Testing price for fixed bundle product + with special price, percent sub items and percent options Configuration #2 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 110 * 1) + 'minimalPrice' => 110, + + // 0.5 * (110 + 2 * 110 * 0.2 + 1 * 110) + 'maximalPrice' => 132 + ] + ], + + ' + Testing price for fixed bundle product + with special price, fixed sub items and percent options Configuration #2 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 110) + 'minimalPrice' => 110, + + // 0.5 * (110 + 2 * 20 + 1 * 110) + 'maximalPrice' => 130 + ] + ], + + ' + Testing price for fixed bundle product + with special price, percent sub items and fixed options Configuration #2 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * 110 + 100 + 'minimalPrice' => 155, + + // 0.5 * (110 + 2 * 0.2 * 110) + 100 + 'maximalPrice' => 177 + ] + ], + + ' + Testing price for fixed bundle product + with special price, fixed sub items and fixed options Configuration #3 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 3 * 10) + 100 + 'minimalPrice' => 170, + + // 0.5 * (110 + 3 * 10 + 1 * 40) + 100 + 'maximalPrice' => 190 + ] + ], + + ' + Testing price for fixed bundle product + with special price, percent sub items and percent options Configuration #3 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 3 * 110 * 0.1 + 110 * 1) + 'minimalPrice' => 126.5, + + // 0.5 * (110 + 3 * 110 * 0.1 + 1 * 110 * 0.4 + 110 * 1) + 'maximalPrice' => 148.5 + ] + ], + + ' + Testing price for fixed bundle product + with special price, fixed sub items and percent options Configuration #3 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 3 * 10 + 1 * 110) + 'minimalPrice' => 125, + + // 0.5 * (110 + 3 * 10 + 1 * 40 + 1 * 110) + 'maximalPrice' => 145 + ] + ], + + ' + Testing price for fixed bundle product + with special price, percent sub items and fixed options Configuration #3 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 3 * 110 * 0.1) + 100 + 'minimalPrice' => 171.5, + + // 0.5 * (110 + 3 * 110 * 0.1 + 1 * 110 * 0.4) + 100 + 'maximalPrice' => 193.5 + ] + ], + + ' + Testing price for fixed bundle product + with special price, fixed sub items and fixed options Configuration #4 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 40) + 100 + 'minimalPrice' => 175, + + // 0.5 * (110 + 1 * 40 + 3 * 15) + 100 + 'maximalPrice' => 197.5 + ] + ], + + ' + Testing price for fixed bundle product + with special price, percent sub items and percent options Configuration #4 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110) + 'minimalPrice' => 132, + + // 0.5 * (110 + 1 * 110 * 0.4 + 3 * 110 * 0.15 + 110 * 1) + 'maximalPrice' => 156.75 + ] + ], + + ' + Testing price for fixed bundle product + with special price, fixed sub items and percent options Configuration #4 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 40 + 1 * 110) + 'minimalPrice' => 130, + + // 0.5 * (110 + 1 * 40 + 3 * 15 + 1 * 110) + 'maximalPrice' => 152.5 + ] + ], + + ' + Testing price for fixed bundle product + with special price, percent sub items and fixed options Configuration #4 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 110 * 0.4) + 100 + 'minimalPrice' => 177, + + // 0.5 * (110 + 1 * 110 * 0.4 + 3 * 110 * 0.15) + 100 + 'maximalPrice' => 201.75 + ] + ], + + ' + Testing price for fixed bundle product + with special price, fixed sub items and fixed options Configuration #5 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 40) + 100 + 'minimalPrice' => 175, + + // 0.5 * (110 + 3 * 15) + 100 + 'maximalPrice' => 177.5 + ] + ], + + ' + Testing price for fixed bundle product + with special price, percent sub items and percent options Configuration #5 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110) + 'minimalPrice' => 132, + + // 0.5 * (110 + 3 * 110 * 0.15 + 1 * 110) + 'maximalPrice' => 134.75 + ] + ], + + ' + Testing price for fixed bundle product + with special price, fixed sub items and percent options Configuration #5 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 40 + 110 * 1) + 'minimalPrice' => 130, + + // 0.5 * (110 + 3 * 15 + 110 * 1) + 'maximalPrice' => 132.5 + ] + ], + + ' + Testing price for fixed bundle product + with special price, percent sub items and fixed options Configuration #5 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 110 * 0.4) + 100 + 'minimalPrice' => 177, + + // 0.5 * (110 + 3 * 110 * 0.15) + 100 + 'maximalPrice' => 179.75 + ] + ], + + ' + Testing price for fixed bundle product + with special price, fixed sub items and fixed options Configuration #6 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 40 + 1 * 20) + 100 + 'minimalPrice' => 185, + + // 0.5 * (110 + 3 * 15 + 1 * 20 + 3 * 10) + 100 + 'maximalPrice' => 202.5 + ] + ], + + ' + Testing price for fixed bundle product + with special price, percent sub items and percent options Configuration #6 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110 * 0.2 + 110 * 1) + 'minimalPrice' => 143, + + // 0.5 * (110 + 3 * 110 * 0.15 + 1 * 110 * 0.2 + 3 * 110 * 0.1 + 110 * 1) + 'maximalPrice' => 162.25 + ] + ], + + ' + Testing price for fixed bundle product + with special price, fixed sub items and percent options Configuration #6 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 40 + 1 * 20 + 1 * 110) + 'minimalPrice' => 140, + + // 0.5 * (110 + 3 * 15 + 1 * 20 + 3 * 10 + 1 * 110) + 'maximalPrice' => 157.5 + ] + ], + + ' + Testing price for fixed bundle product + with special price, percent sub items and fixed options Configuration #6 + ' => [ + 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110 * 0.2) + 100 + 'minimalPrice' => 188, + + // 0.5 * (110 + 3 * 110 * 0.15 + 1 * 110 * 0.2 + 3 * 110 * 0.1) + 100 + 'maximalPrice' => 207.25 + ] + ], + ]; + } + + public function getEmptyProductStrategy() + { + return []; + } + + public function getEmptyProductWithSpecialPriceStrategy() + { + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + ]; + } + + public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 20, + 'price_type' => $selectionsPriceType + ], + ] + ], + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 20, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'required' => false, + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 20, + 'qty' => 2, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 40, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 10, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'type' => 'multi', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 40, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 15, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 40, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 15, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 40, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 15, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ], + [ + 'type' => 'checkbox', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 2, + 'price' => 20, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 2, + 'price' => 10, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSpecialPrice', + 'data' => [50] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + protected function getFixtureForProductOption(array $data = []) + { + $fixture = $this->fixtureForProductOption; + + // make title different for each call + $fixture['title'] .= ' ' . microtime(true); + + return array_merge($fixture, $data); + } + + protected function getFixtureForProductOptionSelection($data) + { + $fixture = $this->fixtureForProductOptionSelection; + + return array_merge($fixture, $data); + } + + protected function getFixtureForProductCustomOption(array $data = []) + { + $fixture = $this->fixtureForProductCustomOption; + + // make title and sku different for each call + $fixture['title'] .= ' ' . microtime(true); + $fixture['sku'] .= ' ' . microtime(true); + + return array_merge($fixture, $data); + } + + protected function addSpecialPrice(\Magento\Catalog\Model\Product $bundleProduct, $discount) + { + $bundleProduct->setSpecialPrice($discount); + + return $bundleProduct; + } + + protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + { + $options = []; + + foreach ($optionsData as $optionData) { + $links = []; + $linksData = $optionData['links']; + unset($optionData['links']); + + $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOption($optionData)]) + ->setSku($bundleProduct->getSku()) + ->setOptionid(null); + + foreach ($linksData as $linkData) { + $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); + } + + $option->setProductLinks($links); + $options[] = $option; + } + + $extension = $bundleProduct->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $bundleProduct->setExtensionAttributes($extension); + + return $bundleProduct; + } + + protected function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + { + /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */ + $customOptionFactory = $this->objectManager + ->create(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); + + $options = []; + foreach ($optionsData as $optionData) { + $customOption = $customOptionFactory->create(['data' => $this->getFixtureForProductCustomOption($optionData)]); + $customOption->setProductSku($bundleProduct->getSku()); + $customOption->setOptionId(null); + + $options[] = $customOption; + } + + $bundleProduct->setOptions($options); + $bundleProduct->setCanSaveCustomOptions(true); + + return $bundleProduct; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php new file mode 100644 index 0000000000000..726b8a36fb301 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php @@ -0,0 +1,27 @@ +create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + +/** @var $product \Magento\Catalog\Model\Product */ +$product = $objectManager->create(\Magento\Catalog\Model\Product::class); +$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) + ->setId(42) + ->setAttributeSetId(4) + ->setWebsiteIds([1]) + ->setName('Spherical Horse in a Vacuum') + ->setSku('spherical_horse_in_a_vacuum') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(1) + ->setPriceType(\Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC) + ->setShipmentType(0); + +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php new file mode 100644 index 0000000000000..1ba272952f895 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php @@ -0,0 +1,25 @@ +get(\Magento\Framework\Registry::class); +$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $product = $productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + $productRepository->delete($product); +} catch (\Magento\Framework\Exception\NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule.php new file mode 100644 index 0000000000000..f4ad5be3048c8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule.php @@ -0,0 +1,8 @@ +create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + +/** @var $product \Magento\Catalog\Model\Product */ +$product = $objectManager->create(\Magento\Catalog\Model\Product::class); +$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) + ->setId(42) + ->setAttributeSetId(4) + ->setWebsiteIds([1]) + ->setName('Spherical Horse in a Vacuum') + ->setSku('spherical_horse_in_a_vacuum') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(1) + ->setPriceType(\Magento\Bundle\Model\Product\Price::PRICE_TYPE_FIXED) + ->setPrice(110.0) + ->setShipmentType(0); + +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php new file mode 100644 index 0000000000000..1ba272952f895 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php @@ -0,0 +1,25 @@ +get(\Magento\Framework\Registry::class); +$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $product = $productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + $productRepository->delete($product); +} catch (\Magento\Framework\Exception\NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_with_catalog_rule.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_with_catalog_rule.php new file mode 100644 index 0000000000000..a2eb0e8b657a0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_with_catalog_rule.php @@ -0,0 +1,8 @@ + Date: Tue, 25 Oct 2016 17:30:46 +0300 Subject: [PATCH 010/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-59254: Write integration tests for \Magento\Bundle\Pricing\Adjustment\Calculator --- ...namicBundleWithTierPriceCalculatorTest.php | 567 ++++++++++++++++++ 1 file changed, 567 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php new file mode 100644 index 0000000000000..e0bd7bf3b6279 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php @@ -0,0 +1,567 @@ + [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ] + ]; + + private $fixtureForProductOption = [ + 'title' => 'Some title', + 'required' => true, + 'type' => 'checkbox' + ]; + + private $fixtureForProductOptionSelection = [ + 'sku' => null, // need to set this + 'option_id' => null, // need to set this + 'qty' => 1, + 'is_default' => true, + 'can_change_quantity' => 0 + ]; + + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class); + $this->tierPriceFactory = $this->objectManager->create(ProductTierPriceInterfaceFactory::class); + } + + /** + * @param $strategyModifiers array + * @param $expectedResults array + * @dataProvider getTestCases + * @magentoAppIsolation enabled + */ + public function testPriceForDynamicBundle(array $strategyModifiers, array $expectedResults) + { + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); + $this->addTierPrice($bundleProduct); + + foreach ($strategyModifiers as $modifier) { + if (method_exists($this, $modifier['modifierName'])) { + array_unshift($modifier['data'], $bundleProduct); + $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); + } + } + + $this->productRepository->save($bundleProduct); + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + + /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ + $priceInfo = $bundleProduct->getPriceInfo(); + $priceCode = \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE; + + $this->assertEquals( + $expectedResults['minimalPrice'], + $priceInfo->getPrice($priceCode)->getMinimalPrice()->getValue(), + 'Failed to check minimal price on product' + ); + + $this->assertEquals( + $expectedResults['maximalPrice'], + $priceInfo->getPrice($priceCode)->getMaximalPrice()->getValue(), + 'Failed to check maximal price on product' + ); + } + + public function getTestCases() + { + return [ + + 'Testing product price with tier price and sub items Configuration #1' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration1(), + 'expectedResults' => [ + // 0.5 * 10 + 'minimalPrice' => 5, + + // 0.5 * 10 + 'maximalPrice' => 5 + ] + ], + + 'Testing product price with tier price and sub items Configuration #2' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration2(), + 'expectedResults' => [ + // 0.5 * 2 * 10 + 'minimalPrice' => 10, + + // 0.5 * 2 * 10 + 'maximalPrice' => 10 + ] + ], + + 'Testing product price with tier price and sub items Configuration #3' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration3(), + 'expectedResults' => [ + // 0.5 * 1 * 10 + 'minimalPrice' => 5, + + // 0.5 * (1 * 10 + 3 * 20) + 'maximalPrice' => 35 + ] + ], + + 'Testing product price with tier price and sub items Configuration #4' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration4(), + 'expectedResults' => [ + // 0.5 * 1 * 10 + 'minimalPrice' => 5, + + // 0.5 * (1 * 10 + 3 * 20) + 'maximalPrice' => 35 + ] + ], + + 'Testing product price with tier price and sub items Configuration #5' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration5(), + 'expectedResults' => [ + // 0.5 * 1 * 10 + 'minimalPrice' => 5, + + // 0.5 * 3 * 20 + 'maximalPrice' => 30 + ] + ], + + 'Testing product price with tier price and sub items Configuration #6' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration6(), + 'expectedResults' => [ + // 0.5 * (1 * 10 + 1 * 10) + 'minimalPrice' => 10, + + // 0.5 * (3 * 20 + 1 * 10 + 3 * 20) + 'maximalPrice' => 65 + ] + ], + + 'Testing product price with tier price and sub items Configuration #7' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration7(), + 'expectedResults' => [ + // 0.5 * (1 * 10) + 'minimalPrice' => 5, + + // 0.5 * (3 * 20 + 1 * 10 + 3 * 20) + 'maximalPrice' => 65 + ] + ], + + 'Testing product price with tier price and sub items Configuration #8' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration8(), + 'expectedResults' => [ + // 0.5 * (1 * 10) + 'minimalPrice' => 5, + + // 0.5 * (3 * 20 + 1 * 10 + 3 * 20) + 'maximalPrice' => 65 + ] + ], + + 'Testing price for dynamic bundle product with tier price on it and on sub item' => [ + 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration10(), + 'expectedResults' => [ + // 0.5 * 1 * 2.5 + 'minimalPrice' => 1.25, + + // 0.5 * 3 * 20 + 'maximalPrice' => 30 + ] + ], + ]; + } + + public function getProductWithSubItemsAndOptionsStrategy() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + ] + ], + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSubItemsAndOptionsStrategyConfiguration1() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSubItemsAndOptionsStrategyConfiguration2() + { + $optionsData = [ + [ + 'required' => false, + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'qty' => 2, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSubItemsAndOptionsStrategyConfiguration3() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSubItemsAndOptionsStrategyConfiguration4() + { + $optionsData = [ + [ + 'type' => 'multi', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSubItemsAndOptionsStrategyConfiguration5() + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSubItemsAndOptionsStrategyConfiguration6() + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ], + [ + 'type' => 'checkbox', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 2, + ], + [ + 'sku' => 'simple2', + 'option_id' => 2, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSubItemsAndOptionsStrategyConfiguration7() + { + $optionsData = [ + [ + 'required' => false, + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ], + [ + 'type' => 'checkbox', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 2, + ], + [ + 'sku' => 'simple2', + 'option_id' => 2, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSubItemsAndOptionsStrategyConfiguration8() + { + $optionsData = [ + [ + 'required' => false, + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ], + [ + 'required' => false, + 'type' => 'checkbox', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 2, + ], + [ + 'sku' => 'simple2', + 'option_id' => 2, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSubItemsAndOptionsStrategyConfiguration10() + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 3, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addTierPriceForSimple', + 'data' => ['simple1', 2.5] + ], + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + protected function getFixtureForProductOption(array $data = []) + { + $fixture = $this->fixtureForProductOption; + + // make title different for each call + $fixture['title'] .= ' ' . microtime(true); + + return array_merge($fixture, $data); + } + + protected function getFixtureForProductOptionSelection($data) + { + $fixture = $this->fixtureForProductOptionSelection; + + return array_merge($fixture, $data); + } + + protected function addTierPriceForSimple(\Magento\Catalog\Model\Product $bundleProduct, $sku, $price) + { + $simple = $this->productRepository->get($sku, false, null, true); + $fixtureForTierPrice = $this->fixtureForTierPrice; + $fixtureForTierPrice['data']['value'] = $price; + $tierPrice = $this->tierPriceFactory->create($fixtureForTierPrice); + $simple->setTierPrices([$tierPrice]); + $this->productRepository->save($simple); + + return $bundleProduct; + } + + protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + { + $options = []; + + foreach ($optionsData as $optionData) { + $links = []; + $linksData = $optionData['links']; + unset($optionData['links']); + + $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOption($optionData)]) + ->setSku($bundleProduct->getSku()) + ->setOptionid(null); + + foreach ($linksData as $linkData) { + $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); + } + + $option->setProductLinks($links); + $options[] = $option; + } + + $extension = $bundleProduct->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $bundleProduct->setExtensionAttributes($extension); + + return $bundleProduct; + } + + private function addTierPrice(\Magento\Catalog\Model\Product $bundleProduct) + { + $tierPrice = $this->tierPriceFactory->create($this->fixtureForTierPrice); + $bundleProduct->setTierPrices([$tierPrice]); + + return $bundleProduct; + } +} From 1f575b98bea6c5be8994c0c2a9f92354d62e45a8 Mon Sep 17 00:00:00 2001 From: Andrii Dimov Date: Tue, 25 Oct 2016 17:50:30 +0300 Subject: [PATCH 011/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-59254: Write integration tests for \Magento\Bundle\Pricing\Adjustment\Calculator --- ...FixedBundleWithTierPriceCalculatorTest.php | 842 ++++++++++++++++++ 1 file changed, 842 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php new file mode 100644 index 0000000000000..5fa864fbdd5d0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php @@ -0,0 +1,842 @@ + [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ] + ]; + + + private $fixtureForProductOption = [ + 'title' => 'Some title', + 'required' => true, + 'type' => 'checkbox' + ]; + + private $fixtureForProductOptionSelection = [ + 'sku' => null, // need to set this + 'option_id' => null, // need to set this + 'qty' => 1, + 'is_default' => true, + 'price' => null, // need to set this + 'price_type' => LinkInterface::PRICE_TYPE_FIXED, + 'can_change_quantity' => 0 + ]; + + private $fixtureForProductCustomOption = [ + 'option_id' => null, + 'previous_group' => 'text', + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'sort_order' => 0, + 'price' => 100, + 'price_type' => 'fixed', + 'sku' => 'for-custom-option', + 'max_characters' => 100, + ]; + + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class); + $this->tierPriceFactory = $this->objectManager->create(ProductTierPriceInterfaceFactory::class); + } + + /** + * @param $strategyModifiers array + * @param $expectedResults array + * @dataProvider getTestCases + * @magentoAppIsolation enabled + */ + public function testPriceForFixedBundle(array $strategyModifiers, array $expectedResults) + { + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); + $this->addTierPrice($bundleProduct); + foreach ($strategyModifiers as $modifier) { + if (method_exists($this, $modifier['modifierName'])) { + array_unshift($modifier['data'], $bundleProduct); + $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); + } + } + + $this->productRepository->save($bundleProduct); + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + + /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ + $priceInfo = $bundleProduct->getPriceInfo(); + $priceCode = \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE; + + $this->assertEquals( + $expectedResults['minimalPrice'], + $priceInfo->getPrice($priceCode)->getMinimalPrice()->getValue(), + 'Failed to check minimal price on product' + ); + + $this->assertEquals( + $expectedResults['maximalPrice'], + $priceInfo->getPrice($priceCode)->getMaximalPrice()->getValue(), + 'Failed to check maximal price on product' + ); + } + + /** + * Test cases for fixed bundle product + * @return array + */ + public function getTestCases() + { + + return [ + + 'Testing product price with tier price and without any sub items and options' => [ + 'strategy' => $this->getEmptyProduct(), + 'expectedResults' => [ + // 110 * 0.5 + 'minimalPrice' => 55, + + // 110 * 0.5 + 'maximalPrice' => 55 + ] + ], + + 'Testing product price with tier price, fixed sub items and fixed options Configuration #1' => [ + 'strategy' => $this->getProductConfiguration1( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 20) + 100 + 'minimalPrice' => 165, + + // 0.5 * (110 + 1 * 20) + 100 + 'maximalPrice' => 165 + ] + ], + + 'Testing product price with tier price, percent sub items and percent options Configuration #1' => [ + 'strategy' => $this->getProductConfiguration1( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 110 * 0.2 + 110 * 1) + 'minimalPrice' => 121, + + // 0.5 * (110 + 110 * 0.2 + 110 * 1) + 'maximalPrice' => 121 + ] + ], + + 'Testing product price with tier price, fixed sub items and percent options Configuration #1' => [ + 'strategy' => $this->getProductConfiguration1( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 20 + 110 * 1) + 'minimalPrice' => 120, + + // 0.5 * (110 + 1 * 20 + 110 * 1) + 'maximalPrice' => 120 + ] + ], + + 'Testing product price with tier price, fixed sub items and percent options Configuration #1' => [ + 'strategy' => $this->getProductConfiguration1( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 20 + 110 * 1) + 'minimalPrice' => 120, + + // 0.5 * (110 + 1 * 20 + 110 * 1) + 'maximalPrice' => 120 + ] + ], + + 'Testing product price with tier price, percent sub items and fixed options Configuration #1' => [ + 'strategy' => $this->getProductConfiguration1( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 110 * 0.2) + 100 + 'minimalPrice' => 166, + + // 0.5 * (110 + 110 * 0.2) + 100 + 'maximalPrice' => 166 + ] + ], + + 'Testing product price with tier price, fixed sub items and fixed options Configuration #2' => [ + 'strategy' => $this->getProductConfiguration2( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * 110 + 100 + 'minimalPrice' => 155, + + // 0.5 * (110 + 2 * 20) + 100 + 'maximalPrice' => 175 + ] + ], + + 'Testing product price with tier price, percent sub items and percent options Configuration #2' => [ + 'strategy' => $this->getProductConfiguration2( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 110 * 1) + 'minimalPrice' => 110, + + // 0.5 * (110 + 2 * 110 * 0.2 + 1 * 110) + 'maximalPrice' => 132 + ] + ], + + 'Testing product price with tier price, fixed sub items and percent options Configuration #2' => [ + 'strategy' => $this->getProductConfiguration2( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 110) + 'minimalPrice' => 110, + + // 0.5 * (110 + 2 * 20 + 1 * 110) + 'maximalPrice' => 130 + ] + ], + + 'Testing product price with tier price, percent sub items and fixed options Configuration #2' => [ + 'strategy' => $this->getProductConfiguration2( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * 110 + 100 + 'minimalPrice' => 155, + + // 0.5 * (110 + 2 * 0.2 * 110) + 100 + 'maximalPrice' => 177 + ] + ], + + 'Testing product price with tier price, fixed sub items and fixed options Configuration #3' => [ + 'strategy' => $this->getProductConfiguration3( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 3 * 10) + 100 + 'minimalPrice' => 170, + + // 0.5 * (110 + 3 * 10 + 1 * 40) + 100 + 'maximalPrice' => 190 + ] + ], + + 'Testing product price with tier price, percent sub items and percent options Configuration #3' => [ + 'strategy' => $this->getProductConfiguration3( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 3 * 110 * 0.1 + 110 * 1) + 'minimalPrice' => 126.5, + + // 0.5 * (110 + 3 * 110 * 0.1 + 1 * 110 * 0.4 + 110 * 1) + 'maximalPrice' => 148.5 + ] + ], + + 'Testing product price with tier price, fixed sub items and percent options Configuration #3' => [ + 'strategy' => $this->getProductConfiguration3( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 3 * 10 + 1 * 110) + 'minimalPrice' => 125, + + // 0.5 * (110 + 3 * 10 + 1 * 40 + 1 * 110) + 'maximalPrice' => 145 + ] + ], + + 'Testing product price with tier price, percent sub items and fixed options Configuration #3' => [ + 'strategy' => $this->getProductConfiguration3( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 3 * 110 * 0.1) + 100 + 'minimalPrice' => 171.5, + + // 0.5 * (110 + 3 * 110 * 0.1 + 1 * 110 * 0.4) + 100 + 'maximalPrice' => 193.5 + ] + ], + + 'Testing product price with tier price, fixed sub items and fixed options Configuration #4' => [ + 'strategy' => $this->getProductConfiguration4( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 40) + 100 + 'minimalPrice' => 175, + + // 0.5 * (110 + 1 * 40 + 3 * 15) + 100 + 'maximalPrice' => 197.5 + ] + ], + + 'Testing product price with tier price, percent sub items and percent options Configuration #4' => [ + 'strategy' => $this->getProductConfiguration4( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110) + 'minimalPrice' => 132, + + // 0.5 * (110 + 1 * 110 * 0.4 + 3 * 110 * 0.15 + 110 * 1) + 'maximalPrice' => 156.75 + ] + ], + + 'Testing product price with tier price, fixed sub items and percent options Configuration #4' => [ + 'strategy' => $this->getProductConfiguration4( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 40 + 1 * 110) + 'minimalPrice' => 130, + + // 0.5 * (110 + 1 * 40 + 3 * 15 + 1 * 110) + 'maximalPrice' => 152.5 + ] + ], + + 'Testing product price with tier price, percent sub items and fixed options Configuration #4' => [ + 'strategy' => $this->getProductConfiguration4( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 110 * 0.4) + 100 + 'minimalPrice' => 177, + + // 0.5 * (110 + 1 * 110 * 0.4 + 3 * 110 * 0.15) + 100 + 'maximalPrice' => 201.75 + ] + ], + + 'Testing product price with tier price, fixed sub items and fixed options Configuration #5' => [ + 'strategy' => $this->getProductConfiguration5( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 40) + 100 + 'minimalPrice' => 175, + + // 0.5 * (110 + 3 * 15) + 100 + 'maximalPrice' => 177.5 + ] + ], + + 'Testing product price with tier price, percent sub items and percent options Configuration #5' => [ + 'strategy' => $this->getProductConfiguration5( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110) + 'minimalPrice' => 132, + + // 0.5 * (110 + 3 * 110 * 0.15 + 1 * 110) + 'maximalPrice' => 134.75 + ] + ], + + 'Testing product price with tier price, fixed sub items and percent options Configuration #5' => [ + 'strategy' => $this->getProductConfiguration5( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 40 + 110 * 1) + 'minimalPrice' => 130, + + // 0.5 * (110 + 3 * 15 + 110 * 1) + 'maximalPrice' => 132.5 + ] + ], + + 'Testing product price with tier price, percent sub items and fixed options Configuration #5' => [ + 'strategy' => $this->getProductConfiguration5( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 110 * 0.4) + 100 + 'minimalPrice' => 177, + + // 0.5 * (110 + 3 * 110 * 0.15) + 100 + 'maximalPrice' => 179.75 + ] + ], + + 'Testing product price with tier price, fixed sub items and fixed options Configuration #6' => [ + 'strategy' => $this->getProductConfiguration6( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 40 + 1 * 20) + 100 + 'minimalPrice' => 185, + + // 0.5 * (110 + 3 * 15 + 1 * 20 + 3 * 10) + 100 + 'maximalPrice' => 202.5 + ] + ], + + 'Testing product price with tier price, percent sub items and percent options Configuration #6' => [ + 'strategy' => $this->getProductConfiguration6( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110 * 0.2 + 110 * 1) + 'minimalPrice' => 143, + + // 0.5 * (110 + 3 * 110 * 0.15 + 1 * 110 * 0.2 + 3 * 110 * 0.1 + 110 * 1) + 'maximalPrice' => 162.25 + ] + ], + + 'Testing product price with tier price, fixed sub items and percent options Configuration #6' => [ + 'strategy' => $this->getProductConfiguration6( + LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 40 + 1 * 20 + 1 * 110) + 'minimalPrice' => 140, + + // 0.5 * (110 + 3 * 15 + 1 * 20 + 3 * 10 + 1 * 110) + 'maximalPrice' => 157.5 + ] + ], + + 'Testing product price with tier price, percent sub items and fixed options Configuration #6' => [ + 'strategy' => $this->getProductConfiguration6( + LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + ), + 'expectedResults' => [ + // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110 * 0.2) + 100 + 'minimalPrice' => 188, + + // 0.5 * (110 + 3 * 110 * 0.15 + 1 * 110 * 0.2 + 3 * 110 * 0.1) + 100 + 'maximalPrice' => 207.25 + ] + ], + + ]; + } + + public function getEmptyProduct() + { + return []; + } + + public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 20, + 'price_type' => $selectionsPriceType + ], + ] + ], + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductConfiguration1($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 20, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductConfiguration2($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'required' => false, + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 20, + 'qty' => 2, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductConfiguration3($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 40, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 10, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductConfiguration4($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'type' => 'multi', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 40, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 15, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductConfiguration5($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 40, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 15, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + public function getProductConfiguration6($selectionsPriceType, $customOptionsPriceType) + { + $optionsData = [ + [ + 'type' => 'radio', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 40, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 15, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ], + [ + 'type' => 'checkbox', + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 2, + 'price' => 20, + 'price_type' => $selectionsPriceType + ], + [ + 'sku' => 'simple2', + 'option_id' => 2, + 'price' => 10, + 'qty' => 3, + 'price_type' => $selectionsPriceType + ], + ] + ] + ]; + + $customOptionsData = [ + [ + 'price_type' => $customOptionsPriceType + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + [ + 'modifierName' => 'addCustomOption', + 'data' => [$customOptionsData] + ], + ]; + } + + private function getFixtureForProductOption(array $data = []) + { + $fixture = $this->fixtureForProductOption; + + // make title different for each call + $fixture['title'] .= ' ' . microtime(true); + + return array_merge($fixture, $data); + } + + private function getFixtureForProductOptionSelection($data) + { + $fixture = $this->fixtureForProductOptionSelection; + + return array_merge($fixture, $data); + } + + private function getFixtureForProductCustomOption(array $data = []) + { + $fixture = $this->fixtureForProductCustomOption; + + // make title and sku different for each call + $fixture['title'] .= ' ' . microtime(true); + $fixture['sku'] .= ' ' . microtime(true); + + return array_merge($fixture, $data); + } + + private function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + { + $options = []; + + foreach ($optionsData as $optionData) { + $links = []; + $linksData = $optionData['links']; + unset($optionData['links']); + + $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOption($optionData)]) + ->setSku($bundleProduct->getSku()) + ->setOptionid(null); + + foreach ($linksData as $linkData) { + $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); + } + + $option->setProductLinks($links); + $options[] = $option; + } + + $extension = $bundleProduct->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $bundleProduct->setExtensionAttributes($extension); + + return $bundleProduct; + } + + private function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + { + /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */ + $customOptionFactory = $this->objectManager + ->create(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); + + $options = []; + foreach ($optionsData as $optionData) { + $customOption = $customOptionFactory->create( + [ + 'data' => $this->getFixtureForProductCustomOption($optionData) + ] + ); + $customOption->setProductSku($bundleProduct->getSku()); + $customOption->setOptionId(null); + + $options[] = $customOption; + } + + $bundleProduct->setOptions($options); + $bundleProduct->setCanSaveCustomOptions(true); + + return $bundleProduct; + } + + private function addTierPrice(\Magento\Catalog\Model\Product $bundleProduct, $percent = false) + { + $tierPrice = $this->tierPriceFactory->create($this->fixtureForTierPrice); + $bundleProduct->setTierPrices([$tierPrice]); + + return $bundleProduct; + } +} From a97f6fc74134115a1749a346f87c9d0335a72298 Mon Sep 17 00:00:00 2001 From: Andrii Dimov Date: Tue, 25 Oct 2016 18:45:59 +0300 Subject: [PATCH 012/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-59254: Write integration tests for \Magento\Bundle\Pricing\Adjustment\Calculator --- ...ndleWithCatalogPriceRuleCalculatorTest.php | 144 +++++++++++------- ...edBundleWithSpecialPriceCalculatorTest.php | 36 ++++- ...FixedBundleWithTierPriceCalculatorTest.php | 84 ++++++---- .../dynamic_bundle_product_rollback.php | 2 +- ...namic_bundle_product_with_catalog_rule.php | 2 +- ...dle_product_with_catalog_rule_rollback.php | 1 - .../fixed_bundle_product_rollback.php | 2 +- ...fixed_bundle_product_with_catalog_rule.php | 2 +- ...dle_product_with_catalog_rule_rollback.php | 1 - 9 files changed, 173 insertions(+), 101 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php index e14088bff2885..be7a38df2a881 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php @@ -118,7 +118,8 @@ public function getTestCases() with catalog price rule, fixed sub items and fixed options ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.9 * 110 + 1 * 20 + 100 @@ -134,7 +135,8 @@ public function getTestCases() with catalog price rule, percent sub items and percent options ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.9 * 110 + 0.9 * 110 * 0.2 + 0.9 * 110 * 1 @@ -150,7 +152,8 @@ public function getTestCases() with catalog price rule, fixed sub items and percent options ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.9 * 110 + 1 * 20 + 0.9 * 110 * 1 @@ -166,7 +169,8 @@ public function getTestCases() with catalog price rule, percent sub items and fixed options ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.9 * 110 + 0.9 * 110 * 0.2 + 100 @@ -181,8 +185,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, fixed sub items and fixed options Configuration #1 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration1( + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.9 * 110 + 1 * 20 + 100 @@ -197,8 +202,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, percent sub items and percent options Configuration #1 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration1( + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.9 * 110 + 0.9 * 110 * 0.2 + 0.9 * 110 * 1 @@ -213,8 +219,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, fixed sub items and percent options Configuration #1 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration1( + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.9 * 110 + 1 * 20 + 0.9 * 110 * 1 @@ -229,8 +236,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, percent sub items and fixed options Configuration #1 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration1( + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.9 * 110 + 0.9 * 110 * 0.2 + 100 @@ -245,8 +253,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, fixed sub items and fixed options Configuration #2 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration2( + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.9 * 110 + 100 @@ -261,8 +270,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, percent sub items and percent options Configuration #2 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration2( + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.9 * 110 + 0.9 * 110 * 1 @@ -277,8 +287,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, fixed sub items and percent options Configuration #2 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration2( + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.9 * 110 + 1 * 0.9 * 110 @@ -293,8 +304,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, percent sub items and fixed options Configuration #2 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration2( + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.9 * 110 + 100 @@ -309,8 +321,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, fixed sub items and fixed options Configuration #3 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration3( + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.9 * 110 + 3 * 10 + 100 @@ -325,8 +338,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, percent sub items and percent options Configuration #3 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration3( + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.9 * 110 + 3 * 0.9 * 110 * 0.1 + 0.9 * 110 * 1 @@ -341,8 +355,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, fixed sub items and percent options Configuration #3 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration3( + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.9 * 110 + 3 * 10 + 1 * 0.9 * 110 @@ -357,8 +372,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, percent sub items and fixed options Configuration #3 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration3( + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.9 * 110 + 3 * 0.9 * 110 * 0.1 + 100 @@ -373,8 +389,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, fixed sub items and fixed options Configuration #4 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration4( + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.9 * 110 + 1 * 40 + 100 @@ -389,8 +406,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, percent sub items and percent options Configuration #4 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration4( + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.9 * 110 + 1 * 0.9 * 110 * 0.4 + 1 * 0.9 * 110 @@ -405,8 +423,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, fixed sub items and percent options Configuration #4 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration4( + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.9 * 110 + 1 * 40 + 1 * 0.9 * 110 @@ -421,8 +440,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, percent sub items and fixed options Configuration #4 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration4( + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.9 * 110 + 1 * 0.9 * 110 * 0.4 + 100 @@ -437,8 +457,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, fixed sub items and fixed options Configuration #5 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration5( + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.9 * 110 + 1 * 40 + 100 @@ -453,8 +474,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, percent sub items and percent options Configuration #5 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration5( + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.9 * 110 + 1 * 0.9 * 110 * 0.4 + 1 * 0.9 * 110 @@ -469,8 +491,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, fixed sub items and percent options Configuration #5 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration5( + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.9 * 110 + 1 * 40 + 0.9 * 110 * 1 @@ -485,8 +508,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, percent sub items and fixed options Configuration #5 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration5( + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.9 * 110 + 1 * 0.9 * 110 * 0.4 + 100 @@ -501,8 +525,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, fixed sub items and fixed options Configuration #6 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration6( + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.9 * 110 + 1 * 40 + 1 * 20 + 100 @@ -517,8 +542,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, percent sub items and percent options Configuration #6 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration6( + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.9 * 110 + 1 * 0.9 * 110 * 0.4 + 1 * 0.9 * 110 * 0.2 + 0.9 * 110 * 1 @@ -533,8 +559,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, fixed sub items and percent options Configuration #6 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration6( + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.9 * 110 + 1 * 40 + 1 * 20 + 1 * 0.9 * 110 @@ -549,8 +576,9 @@ public function getTestCases() Testing price for fixed bundle product with catalog price rule, percent sub items and fixed options Configuration #6 ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration6( + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.9 * 110 + 1 * 0.9 * 110 * 0.4 + 1 * 0.9 * 110 * 0.2 + 100 @@ -601,7 +629,7 @@ public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $ ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1($selectionsPriceType, $customOptionsPriceType) + public function getProductSubItemsAndOptionsStrategyConfiguration1($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -634,7 +662,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2($selectionsPriceType, $customOptionsPriceType) + public function getProductSubItemsAndOptionsStrategyConfiguration2($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -669,7 +697,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3($selectionsPriceType, $customOptionsPriceType) + public function getProductSubItemsAndOptionsStrategyConfiguration3($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -709,7 +737,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4($selectionsPriceType, $customOptionsPriceType) + public function getProductSubItemsAndOptionsStrategyConfiguration4($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -750,7 +778,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5($selectionsPriceType, $customOptionsPriceType) + public function getProductSubItemsAndOptionsStrategyConfiguration5($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -791,7 +819,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6($selectionsPriceType, $customOptionsPriceType) + public function getProductSubItemsAndOptionsStrategyConfiguration6($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php index 4482c56cab9b0..68e15e18f8613 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php @@ -625,7 +625,10 @@ public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $ ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1($selectionsPriceType, $customOptionsPriceType) + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + $selectionsPriceType, + $customOptionsPriceType + ) { $optionsData = [ [ @@ -662,7 +665,10 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2($selectionsPriceType, $customOptionsPriceType) + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + $selectionsPriceType, + $customOptionsPriceType + ) { $optionsData = [ [ @@ -701,7 +707,10 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3($selectionsPriceType, $customOptionsPriceType) + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + $selectionsPriceType, + $customOptionsPriceType + ) { $optionsData = [ [ @@ -745,7 +754,10 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4($selectionsPriceType, $customOptionsPriceType) + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + $selectionsPriceType, + $customOptionsPriceType + ) { $optionsData = [ [ @@ -790,7 +802,10 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5($selectionsPriceType, $customOptionsPriceType) + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + $selectionsPriceType, + $customOptionsPriceType + ) { $optionsData = [ [ @@ -835,7 +850,10 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6($selectionsPriceType, $customOptionsPriceType) + public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + $selectionsPriceType, + $customOptionsPriceType + ) { $optionsData = [ [ @@ -971,7 +989,11 @@ protected function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct $options = []; foreach ($optionsData as $optionData) { - $customOption = $customOptionFactory->create(['data' => $this->getFixtureForProductCustomOption($optionData)]); + $customOption = $customOptionFactory->create( + [ + 'data' => $this->getFixtureForProductCustomOption($optionData) + ] + ); $customOption->setProductSku($bundleProduct->getSku()); $customOption->setOptionId(null); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php index 5fa864fbdd5d0..36482b9b83342 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php @@ -16,7 +16,7 @@ * @magentoDataFixture Magento/Bundle/_files/PriceCalculator/fixed_bundle_product.php * @magentoAppArea frontend */ -class FixedBundleWithTierPRiceCalculatorTest extends \PHPUnit_Framework_TestCase +class FixedBundleWithTierPriceCalculatorTest extends \PHPUnit_Framework_TestCase { const CUSTOM_OPTION_PRICE_TYPE_FIXED = 'fixed'; @@ -40,7 +40,6 @@ class FixedBundleWithTierPRiceCalculatorTest extends \PHPUnit_Framework_TestCase ] ]; - private $fixtureForProductOption = [ 'title' => 'Some title', 'required' => true, @@ -136,7 +135,8 @@ public function getTestCases() 'Testing product price with tier price, fixed sub items and fixed options Configuration #1' => [ 'strategy' => $this->getProductConfiguration1( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 1 * 20) + 100 @@ -149,7 +149,8 @@ public function getTestCases() 'Testing product price with tier price, percent sub items and percent options Configuration #1' => [ 'strategy' => $this->getProductConfiguration1( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 110 * 0.2 + 110 * 1) @@ -162,7 +163,8 @@ public function getTestCases() 'Testing product price with tier price, fixed sub items and percent options Configuration #1' => [ 'strategy' => $this->getProductConfiguration1( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 20 + 110 * 1) @@ -175,7 +177,8 @@ public function getTestCases() 'Testing product price with tier price, fixed sub items and percent options Configuration #1' => [ 'strategy' => $this->getProductConfiguration1( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 20 + 110 * 1) @@ -188,7 +191,8 @@ public function getTestCases() 'Testing product price with tier price, percent sub items and fixed options Configuration #1' => [ 'strategy' => $this->getProductConfiguration1( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 110 * 0.2) + 100 @@ -201,7 +205,8 @@ public function getTestCases() 'Testing product price with tier price, fixed sub items and fixed options Configuration #2' => [ 'strategy' => $this->getProductConfiguration2( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * 110 + 100 @@ -214,7 +219,8 @@ public function getTestCases() 'Testing product price with tier price, percent sub items and percent options Configuration #2' => [ 'strategy' => $this->getProductConfiguration2( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 110 * 1) @@ -227,7 +233,8 @@ public function getTestCases() 'Testing product price with tier price, fixed sub items and percent options Configuration #2' => [ 'strategy' => $this->getProductConfiguration2( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 110) @@ -240,7 +247,8 @@ public function getTestCases() 'Testing product price with tier price, percent sub items and fixed options Configuration #2' => [ 'strategy' => $this->getProductConfiguration2( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * 110 + 100 @@ -253,7 +261,8 @@ public function getTestCases() 'Testing product price with tier price, fixed sub items and fixed options Configuration #3' => [ 'strategy' => $this->getProductConfiguration3( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 3 * 10) + 100 @@ -266,7 +275,8 @@ public function getTestCases() 'Testing product price with tier price, percent sub items and percent options Configuration #3' => [ 'strategy' => $this->getProductConfiguration3( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 3 * 110 * 0.1 + 110 * 1) @@ -279,7 +289,8 @@ public function getTestCases() 'Testing product price with tier price, fixed sub items and percent options Configuration #3' => [ 'strategy' => $this->getProductConfiguration3( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 3 * 10 + 1 * 110) @@ -292,7 +303,8 @@ public function getTestCases() 'Testing product price with tier price, percent sub items and fixed options Configuration #3' => [ 'strategy' => $this->getProductConfiguration3( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 3 * 110 * 0.1) + 100 @@ -305,7 +317,8 @@ public function getTestCases() 'Testing product price with tier price, fixed sub items and fixed options Configuration #4' => [ 'strategy' => $this->getProductConfiguration4( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 1 * 40) + 100 @@ -318,7 +331,8 @@ public function getTestCases() 'Testing product price with tier price, percent sub items and percent options Configuration #4' => [ 'strategy' => $this->getProductConfiguration4( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110) @@ -331,7 +345,8 @@ public function getTestCases() 'Testing product price with tier price, fixed sub items and percent options Configuration #4' => [ 'strategy' => $this->getProductConfiguration4( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 40 + 1 * 110) @@ -344,7 +359,8 @@ public function getTestCases() 'Testing product price with tier price, percent sub items and fixed options Configuration #4' => [ 'strategy' => $this->getProductConfiguration4( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 1 * 110 * 0.4) + 100 @@ -357,7 +373,8 @@ public function getTestCases() 'Testing product price with tier price, fixed sub items and fixed options Configuration #5' => [ 'strategy' => $this->getProductConfiguration5( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 1 * 40) + 100 @@ -370,7 +387,8 @@ public function getTestCases() 'Testing product price with tier price, percent sub items and percent options Configuration #5' => [ 'strategy' => $this->getProductConfiguration5( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110) @@ -383,7 +401,8 @@ public function getTestCases() 'Testing product price with tier price, fixed sub items and percent options Configuration #5' => [ 'strategy' => $this->getProductConfiguration5( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 40 + 110 * 1) @@ -396,7 +415,8 @@ public function getTestCases() 'Testing product price with tier price, percent sub items and fixed options Configuration #5' => [ 'strategy' => $this->getProductConfiguration5( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 1 * 110 * 0.4) + 100 @@ -409,7 +429,8 @@ public function getTestCases() 'Testing product price with tier price, fixed sub items and fixed options Configuration #6' => [ 'strategy' => $this->getProductConfiguration6( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 1 * 40 + 1 * 20) + 100 @@ -422,7 +443,8 @@ public function getTestCases() 'Testing product price with tier price, percent sub items and percent options Configuration #6' => [ 'strategy' => $this->getProductConfiguration6( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110 * 0.2 + 110 * 1) @@ -435,7 +457,8 @@ public function getTestCases() 'Testing product price with tier price, fixed sub items and percent options Configuration #6' => [ 'strategy' => $this->getProductConfiguration6( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 40 + 1 * 20 + 1 * 110) @@ -448,7 +471,8 @@ public function getTestCases() 'Testing product price with tier price, percent sub items and fixed options Configuration #6' => [ 'strategy' => $this->getProductConfiguration6( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110 * 0.2) + 100 @@ -777,7 +801,7 @@ private function getFixtureForProductCustomOption(array $data = []) return array_merge($fixture, $data); } - private function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) { $options = []; @@ -807,7 +831,7 @@ private function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, return $bundleProduct; } - private function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + protected function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) { /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */ $customOptionFactory = $this->objectManager @@ -832,7 +856,7 @@ private function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct, return $bundleProduct; } - private function addTierPrice(\Magento\Catalog\Model\Product $bundleProduct, $percent = false) + private function addTierPrice(\Magento\Catalog\Model\Product $bundleProduct) { $tierPrice = $this->tierPriceFactory->create($this->fixtureForTierPrice); $bundleProduct->setTierPrices([$tierPrice]); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php index 1ba272952f895..4f42bba96c177 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php @@ -22,4 +22,4 @@ } $registry->unregister('isSecureArea'); -$registry->register('isSecureArea', false); \ No newline at end of file +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule.php index f4ad5be3048c8..3b4f9bfe97c6d 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule.php @@ -5,4 +5,4 @@ */ require __DIR__ . '/dynamic_bundle_product.php.php'; -require __DIR__ . '/../../../CatalogRule/_files/catalog_rule_10_off_not_logged.php'; \ No newline at end of file +require __DIR__ . '/../../../CatalogRule/_files/catalog_rule_10_off_not_logged.php'; diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule_rollback.php index 5f1d016e15446..51d234e56ab8b 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule_rollback.php @@ -5,4 +5,3 @@ */ require __DIR__ . '/dynamic_bundle_product.php'; - diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php index 1ba272952f895..4f42bba96c177 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php @@ -22,4 +22,4 @@ } $registry->unregister('isSecureArea'); -$registry->register('isSecureArea', false); \ No newline at end of file +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_with_catalog_rule.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_with_catalog_rule.php index a2eb0e8b657a0..6e6c48b8ac9da 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_with_catalog_rule.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_with_catalog_rule.php @@ -5,4 +5,4 @@ */ require __DIR__ . '/fixed_bundle_product.php'; -require __DIR__ . '/../../../CatalogRule/_files/catalog_rule_10_off_not_logged.php'; \ No newline at end of file +require __DIR__ . '/../../../CatalogRule/_files/catalog_rule_10_off_not_logged.php'; diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_with_catalog_rule_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_with_catalog_rule_rollback.php index f6988446de077..8a0059e120851 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_with_catalog_rule_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_with_catalog_rule_rollback.php @@ -5,4 +5,3 @@ */ require __DIR__ . '/fixed_bundle_product_rollback.php'; - From 2e5ce806f23881261816211cd0f55316d7c1f800 Mon Sep 17 00:00:00 2001 From: Andrii Dimov Date: Tue, 25 Oct 2016 19:00:31 +0300 Subject: [PATCH 013/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-59254: Write integration tests for \Magento\Bundle\Pricing\Adjustment\Calculator --- ...icBundleWithSpecialPriceCalculatorTest.php | 21 ---- ...namicBundleWithTierPriceCalculatorTest.php | 18 ---- ...ndleWithCatalogPriceRuleCalculatorTest.php | 6 +- ...edBundleWithSpecialPriceCalculatorTest.php | 102 +++++++++++------- 4 files changed, 67 insertions(+), 80 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php index 1f45a114c3d3c..9762df3a5ddaf 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php @@ -83,117 +83,96 @@ public function getTestCases() 'expectedResults' => [ // just price from simple1 'minimalPrice' => 10, - // just price from simple1 'maximalPrice' => 10 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #1' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1(), 'expectedResults' => [ // 0.5 * 10 'minimalPrice' => 5, - // 0.5 * 10 'maximalPrice' => 5 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #2' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2(), 'expectedResults' => [ // 0.5 * 2 * 10 'minimalPrice' => 10, - // 0.5 * 2 * 10 'maximalPrice' => 10 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #3' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3(), 'expectedResults' => [ // 0.5 * 1 * 10 'minimalPrice' => 5, - // 0.5 * (1 * 10 + 3 * 20) 'maximalPrice' => 35 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #4' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4(), 'expectedResults' => [ // 0.5 * 1 * 10 'minimalPrice' => 5, - // 0.5 * (1 * 10 + 3 * 20) 'maximalPrice' => 35 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #5' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5(), 'expectedResults' => [ // 0.5 * 1 * 10 'minimalPrice' => 5, - // 0.5 * 3 * 20 'maximalPrice' => 30 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #6' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6(), 'expectedResults' => [ // 0.5 * (1 * 10 + 1 * 10) 'minimalPrice' => 10, - // 0.5 * (3 * 20 + 1 * 10 + 3 * 20) 'maximalPrice' => 65 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #7' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration7(), 'expectedResults' => [ // 0.5 * (1 * 10) 'minimalPrice' => 5, - // 0.5 * (3 * 20 + 1 * 10 + 3 * 20) 'maximalPrice' => 65 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #8' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration8(), 'expectedResults' => [ // 0.5 * (1 * 10) 'minimalPrice' => 5, - // 0.5 * (3 * 20 + 1 * 10 + 3 * 20) 'maximalPrice' => 65 ] ], - 'Testing price for dynamic bundle product with sub item product that has special price' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration9(), 'expectedResults' => [ // 1 * 3.5 'minimalPrice' => 3.5, - // 1 * 20 'maximalPrice' => 20 ] ], - 'Testing price for dynamic bundle product with special price on it and on sub item' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration10(), 'expectedResults' => [ // 0.5 * 1 * 3.5 'minimalPrice' => 1.75, - // 0.5 * 3 * 20 'maximalPrice' => 30 ] diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php index e0bd7bf3b6279..801dba66a8e86 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php @@ -94,101 +94,83 @@ public function testPriceForDynamicBundle(array $strategyModifiers, array $expec public function getTestCases() { return [ - 'Testing product price with tier price and sub items Configuration #1' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration1(), 'expectedResults' => [ // 0.5 * 10 'minimalPrice' => 5, - // 0.5 * 10 'maximalPrice' => 5 ] ], - 'Testing product price with tier price and sub items Configuration #2' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration2(), 'expectedResults' => [ // 0.5 * 2 * 10 'minimalPrice' => 10, - // 0.5 * 2 * 10 'maximalPrice' => 10 ] ], - 'Testing product price with tier price and sub items Configuration #3' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration3(), 'expectedResults' => [ // 0.5 * 1 * 10 'minimalPrice' => 5, - // 0.5 * (1 * 10 + 3 * 20) 'maximalPrice' => 35 ] ], - 'Testing product price with tier price and sub items Configuration #4' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration4(), 'expectedResults' => [ // 0.5 * 1 * 10 'minimalPrice' => 5, - // 0.5 * (1 * 10 + 3 * 20) 'maximalPrice' => 35 ] ], - 'Testing product price with tier price and sub items Configuration #5' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration5(), 'expectedResults' => [ // 0.5 * 1 * 10 'minimalPrice' => 5, - // 0.5 * 3 * 20 'maximalPrice' => 30 ] ], - 'Testing product price with tier price and sub items Configuration #6' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration6(), 'expectedResults' => [ // 0.5 * (1 * 10 + 1 * 10) 'minimalPrice' => 10, - // 0.5 * (3 * 20 + 1 * 10 + 3 * 20) 'maximalPrice' => 65 ] ], - 'Testing product price with tier price and sub items Configuration #7' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration7(), 'expectedResults' => [ // 0.5 * (1 * 10) 'minimalPrice' => 5, - // 0.5 * (3 * 20 + 1 * 10 + 3 * 20) 'maximalPrice' => 65 ] ], - 'Testing product price with tier price and sub items Configuration #8' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration8(), 'expectedResults' => [ // 0.5 * (1 * 10) 'minimalPrice' => 5, - // 0.5 * (3 * 20 + 1 * 10 + 3 * 20) 'maximalPrice' => 65 ] ], - 'Testing price for dynamic bundle product with tier price on it and on sub item' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration10(), 'expectedResults' => [ // 0.5 * 1 * 2.5 'minimalPrice' => 1.25, - // 0.5 * 3 * 20 'maximalPrice' => 30 ] diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php index be7a38df2a881..f5c72da722639 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php @@ -944,7 +944,11 @@ protected function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct $options = []; foreach ($optionsData as $optionData) { - $customOption = $customOptionFactory->create(['data' => $this->getFixtureForProductCustomOption($optionData)]); + $customOption = $customOptionFactory->create( + [ + 'data' => $this->getFixtureForProductCustomOption($optionData) + ] + ); $customOption->setProductSku($bundleProduct->getSku()); $customOption->setOptionId(null); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php index 68e15e18f8613..6b0572a0b1164 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php @@ -132,7 +132,8 @@ public function getTestCases() with fixed sub items, fixed options and without any discounts ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 110 + 1 * 20 + 100 @@ -148,7 +149,8 @@ public function getTestCases() with percent sub items, percent options and without any discounts ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 110 + 110 * 0.2 + 110 * 1 @@ -164,7 +166,8 @@ public function getTestCases() with fixed sub items, percent options and without any discounts ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 110 + 1 * 20 + 110 * 1 @@ -180,7 +183,8 @@ public function getTestCases() with percent sub items, fixed options and without any discounts ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 110 + 110 * 0.2 + 100 @@ -196,7 +200,8 @@ public function getTestCases() with special price, fixed sub items and fixed options Configuration #1 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 1 * 20) + 100 @@ -212,7 +217,8 @@ public function getTestCases() with special price, percent sub items and percent options Configuration #1 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 110 * 0.2 + 110 * 1) @@ -228,7 +234,8 @@ public function getTestCases() with special price, fixed sub items and percent options Configuration #1 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 20 + 110 * 1) @@ -244,7 +251,8 @@ public function getTestCases() with special price, percent sub items and fixed options Configuration #1 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 110 * 0.2) + 100 @@ -260,7 +268,8 @@ public function getTestCases() with special price, fixed sub items and fixed options Configuration #2 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * 110 + 100 @@ -276,7 +285,8 @@ public function getTestCases() with special price, percent sub items and percent options Configuration #2 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 110 * 1) @@ -292,7 +302,8 @@ public function getTestCases() with special price, fixed sub items and percent options Configuration #2 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 110) @@ -308,7 +319,8 @@ public function getTestCases() with special price, percent sub items and fixed options Configuration #2 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * 110 + 100 @@ -324,7 +336,8 @@ public function getTestCases() with special price, fixed sub items and fixed options Configuration #3 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 3 * 10) + 100 @@ -340,7 +353,8 @@ public function getTestCases() with special price, percent sub items and percent options Configuration #3 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 3 * 110 * 0.1 + 110 * 1) @@ -356,7 +370,8 @@ public function getTestCases() with special price, fixed sub items and percent options Configuration #3 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 3 * 10 + 1 * 110) @@ -372,7 +387,8 @@ public function getTestCases() with special price, percent sub items and fixed options Configuration #3 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 3 * 110 * 0.1) + 100 @@ -388,7 +404,8 @@ public function getTestCases() with special price, fixed sub items and fixed options Configuration #4 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 1 * 40) + 100 @@ -404,7 +421,8 @@ public function getTestCases() with special price, percent sub items and percent options Configuration #4 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110) @@ -420,7 +438,8 @@ public function getTestCases() with special price, fixed sub items and percent options Configuration #4 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 40 + 1 * 110) @@ -436,7 +455,8 @@ public function getTestCases() with special price, percent sub items and fixed options Configuration #4 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 1 * 110 * 0.4) + 100 @@ -452,7 +472,8 @@ public function getTestCases() with special price, fixed sub items and fixed options Configuration #5 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 1 * 40) + 100 @@ -468,7 +489,8 @@ public function getTestCases() with special price, percent sub items and percent options Configuration #5 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110) @@ -484,7 +506,8 @@ public function getTestCases() with special price, fixed sub items and percent options Configuration #5 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 40 + 110 * 1) @@ -500,7 +523,8 @@ public function getTestCases() with special price, percent sub items and fixed options Configuration #5 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 1 * 110 * 0.4) + 100 @@ -516,7 +540,8 @@ public function getTestCases() with special price, fixed sub items and fixed options Configuration #6 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 1 * 40 + 1 * 20) + 100 @@ -532,7 +557,8 @@ public function getTestCases() with special price, percent sub items and percent options Configuration #6 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110 * 0.2 + 110 * 1) @@ -548,7 +574,8 @@ public function getTestCases() with special price, fixed sub items and percent options Configuration #6 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( - LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT + LinkInterface::PRICE_TYPE_FIXED, + self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), 'expectedResults' => [ // 0.5 * (110 + 1 * 40 + 1 * 20 + 1 * 110) @@ -564,7 +591,8 @@ public function getTestCases() with special price, percent sub items and fixed options Configuration #6 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( - LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED + LinkInterface::PRICE_TYPE_PERCENT, + self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), 'expectedResults' => [ // 0.5 * (110 + 1 * 110 * 0.4 + 1 * 110 * 0.2) + 100 @@ -628,8 +656,7 @@ public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( $selectionsPriceType, $customOptionsPriceType - ) - { + ) { $optionsData = [ [ 'links' => [ @@ -668,8 +695,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( $selectionsPriceType, $customOptionsPriceType - ) - { + ) { $optionsData = [ [ 'required' => false, @@ -710,8 +736,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( $selectionsPriceType, $customOptionsPriceType - ) - { + ) { $optionsData = [ [ 'links' => [ @@ -757,8 +782,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( $selectionsPriceType, $customOptionsPriceType - ) - { + ) { $optionsData = [ [ 'type' => 'multi', @@ -805,8 +829,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( $selectionsPriceType, $customOptionsPriceType - ) - { + ) { $optionsData = [ [ 'type' => 'radio', @@ -853,8 +876,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( $selectionsPriceType, $customOptionsPriceType - ) - { + ) { $optionsData = [ [ 'type' => 'radio', From 53cc8ece1147800821e6606f326a58002e58cd7c Mon Sep 17 00:00:00 2001 From: Andrii Dimov Date: Tue, 25 Oct 2016 19:04:55 +0300 Subject: [PATCH 014/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-59254: Write integration tests for \Magento\Bundle\Pricing\Adjustment\Calculator --- .../dynamic_bundle_product_with_catalog_rule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule.php index 3b4f9bfe97c6d..bb67fb6dfb19c 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule.php @@ -4,5 +4,5 @@ * See COPYING.txt for license details. */ -require __DIR__ . '/dynamic_bundle_product.php.php'; +require __DIR__ . '/dynamic_bundle_product.php'; require __DIR__ . '/../../../CatalogRule/_files/catalog_rule_10_off_not_logged.php'; From c84a3e059f745053ae56d3ae0c85483f796a634b Mon Sep 17 00:00:00 2001 From: Andrii Dimov Date: Tue, 25 Oct 2016 19:30:15 +0300 Subject: [PATCH 015/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-59254: Write integration tests for \Magento\Bundle\Pricing\Adjustment\Calculator --- app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php index f9a7442180f4b..e8d09144a42c5 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php @@ -202,7 +202,7 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR $priceList[] = $this->selectionFactory->create( $bundleProduct, $selection, - $selection->getSelectionQty(), + $bundleProduct->getSelectionQty(), [ 'useRegularPrice' => $useRegularPrice, ] @@ -222,7 +222,7 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR $priceList[] = $this->selectionFactory->create( $bundleProduct, $selection, - $selection->getSelectionQty(), + $bundleProduct->getSelectionQty(), [ 'useRegularPrice' => $useRegularPrice, ] From d9ce136c22fcdc0a36f6c01064a64999f20365c1 Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Wed, 26 Oct 2016 11:24:49 +0300 Subject: [PATCH 016/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - integration test for isSaleable() on product --- .../Bundle/Model/Product/IsSaleableTest.php | 350 ++++++++++++++++++ .../Bundle/_files/issaleable_product.php | 210 +++++++++++ .../_files/issaleable_product_rollback.php | 27 ++ .../Bundle/_files/multiple_products.php | 128 +++++++ .../_files/multiple_products_rollback.php | 28 ++ 5 files changed, 743 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php new file mode 100644 index 0000000000000..20d0fb2e21f1f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php @@ -0,0 +1,350 @@ +objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); + } + + /** + * check bundle product is saleable if his status is enabled + * + * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnEnabledStatus() + { + + $bundleProduct = $this->productRepository->get('bundle-product'); + $bundleProduct->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED); + + $this->assertTrue( + $bundleProduct->isSalable(), + 'Bundle product supposed to be saleable if his status is enabled' + ); + } + + /** + * check bundle product is NOT saleable if his status is disabled + * + * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnDisabledStatus() + { + $bundleProduct = $this->productRepository->get('bundle-product'); + $bundleProduct->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED); + + $this->assertFalse( + $bundleProduct->isSalable(), + 'Bundle product supposed to be non saleable if his status is disabled' + ); + } + + /** + * check bundle product is saleable if his status is enabled + * and it has internal data is_salable = true + * + * @magentoDataFixtureBeforeTransaction Magento/Bundle/_files/issaleable_product.php + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnEnabledStatusAndIsSalableIsTrue() + { + $bundleProduct = $this->productRepository->get('bundle-product'); + $bundleProduct->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED); + $bundleProduct->setData('is_salable', true); + + $this->assertTrue( + $bundleProduct->isSalable(), + 'Bundle product supposed to be saleable if his status is enabled and it has data is_salable = true' + ); + } + + /** + * check bundle product is NOT saleable if + * his status is enabled but his data is_salable = false + * + * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnEnabledStatusAndIsSalableIsFalse() + { + $bundleProduct = $this->productRepository->get('bundle-product'); + $bundleProduct->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED); + $bundleProduct->setData('is_salable', false); + + $this->assertFalse( + $bundleProduct->isSalable(), + 'Bundle product supposed to be non saleable if his status is enabled but his data is_salable = false' + ); + } + + /** + * check bundle product is saleable if it has all_items_salable = true + * + * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnAllItemsSalableIsTrue() + { + $bundleProduct = $this->productRepository->get('bundle-product'); + $bundleProduct->setData('all_items_salable', true); + + $this->assertTrue( + $bundleProduct->isSalable(), + 'Bundle product supposed to be saleable if it has data all_items_salable = true' + ); + } + + /** + * check bundle product is NOT saleable if it has all_items_salable = false + * + * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnAllItemsSalableIsFalse() + { + $bundleProduct = $this->productRepository->get('bundle-product'); + $bundleProduct->setData('all_items_salable', false); + + $this->assertFalse( + $bundleProduct->isSalable(), + 'Bundle product supposed to be non saleable if it has data all_items_salable = false' + ); + } + + /** + * check bundle product is NOT saleable if it has no options + * + * @magentoDataFixtureBeforeTransaction Magento/Bundle/_files/issaleable_product.php + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnBundleWithoutOptions() + { + $optionRepository = $this->objectManager->create(\Magento\Bundle\Api\ProductOptionRepositoryInterface::class); + + $bundleProduct = $this->productRepository->get('bundle-product'); + + // TODO: make cleaner option deletion after fix MAGETWO-59465 + $ea = $bundleProduct->getExtensionAttributes(); + foreach ($ea->getBundleProductOptions() as $option) { + $optionRepository->delete($option); + } + $ea->setBundleProductOptions([]); + $bundleProduct->setExtensionAttributes($ea); + $bundleProduct->setBundleOptionsData([]); + $this->productRepository->save($bundleProduct); + + $this->assertFalse( + $bundleProduct->isSalable(), + 'Bundle product supposed to be non saleable if it has no options' + ); + } + + /** + * check bundle product is NOT saleable if it has no selections + * + * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnBundleWithoutSelections() + { + $bundleProductSku = 'bundle-product'; + + $bundleProduct = $this->productRepository->get($bundleProductSku, true, null, true); + $bundleType = $bundleProduct->getTypeInstance(); + /** @var \Magento\Bundle\Model\LinkManagement $linkManager */ + $linkManager = $this->objectManager->create(\Magento\Bundle\Model\LinkManagement::class); + + /** @var \Magento\Bundle\Model\Product\Type $bundleType */ + $options = $bundleType->getOptionsCollection($bundleProduct); + $selections = $bundleType->getSelectionsCollection($options->getAllIds(), $bundleProduct); + + foreach ($selections as $link) { + /** @var \Magento\Bundle\Model\Selection $link */ + $linkManager->removeChild($bundleProductSku, $link->getOptionId(), $link->getSku()); + } + + $bundleProduct = $this->productRepository->get($bundleProductSku, true, null, true); + + $this->assertFalse( + $bundleProduct->isSalable(), + 'Bundle product supposed to be non saleable if it has no selections' + ); + } + + /** + * check bundle product is NOT saleable if + * all his selections are not saleable + * + * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnBundleWithoutSaleableSelections() + { + $productsSku = ['simple1', 'simple2', 'simple3', 'simple4', 'simple5']; + foreach ($productsSku as $productSku) { + $product = $this->productRepository->get($productSku); + $product->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED); + $this->productRepository->save($product); + } + + $bundleProduct = $this->productRepository->get('bundle-product'); + + $this->assertFalse( + $bundleProduct->isSalable(), + 'Bundle product supposed to be non saleable if all his selections are not saleable' + ); + } + + /** + * check bundle product is NOT saleable if + * it has at least one required option without saleable selections + * + * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnBundleWithoutSaleableSelectionsOnRequiredOption() + { + $productsSku = ['simple1', 'simple2', 'simple3']; + foreach ($productsSku as $productSku) { + $product = $this->productRepository->get($productSku); + $product->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED); + $this->productRepository->save($product); + } + + $bundleProduct = $this->productRepository->get('bundle-product'); + + $this->assertFalse( + $bundleProduct->isSalable(), + 'Bundle product supposed to be non saleable if it has at least one required option with no saleable selections' + ); + } + + /** + * check bundle product is NOT saleable if + * there are not enough qty of selection on required option + * + * @magentoDataFixtureBeforeTransaction Magento/Bundle/_files/issaleable_product.php + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnBundleWithNotEnoughQtyOfSelection() + { + $this->setQtyForSelections(['simple1', 'simple2', 'simple3'], 1); + + $bundleProduct = $this->productRepository->get('bundle-product'); + + $this->assertFalse( + $bundleProduct->isSalable(), + 'Bundle product supposed to be non saleable if there are not enough qty of selections on required options' + ); + } + + /** + * check bundle product is saleable if + * all his selections has not selection qty + * + * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnBundleWithoutSelectionQty() + { + $this->setQtyForSelections(['simple1', 'simple2', 'simple3', 'simple4', 'simple5'], 1); + + $bundleProduct = $this->productRepository->get('bundle-product', false, null, true); + $bundleType = $bundleProduct->getTypeInstance(); + + /** @var \Magento\Bundle\Model\Product\Type $bundleType */ + $options = $bundleType->getOptionsCollection($bundleProduct); + $selections = $bundleType->getSelectionsCollection($options->getAllIds(), $bundleProduct); + + foreach ($selections as $link) { + $link->setSelectionQty(null); + } + + $bundleProduct->setBundleOptionsData([]); + $bundleProduct->setBundleSelectionsData([]); + $this->productRepository->save($bundleProduct); + + $this->assertTrue( + $bundleProduct->isSalable(), + 'Bundle product supposed to be saleable if all his selections has no selection qty' + ); + } + + /** + * check bundle product is saleable if + * all his selections have selection_can_change_qty = 1 + * + * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnBundleWithSelectionCanChangeQty() + { + $this->setQtyForSelections(['simple1', 'simple2', 'simple3', 'simple4', 'simple5'], 1); + + $bundleProduct = $this->productRepository->get('bundle-product', false, null, true); + $bundleType = $bundleProduct->getTypeInstance(); + + /** @var \Magento\Bundle\Model\Product\Type $bundleType */ + $options = $bundleType->getOptionsCollection($bundleProduct); + $selections = $bundleType->getSelectionsCollection($options->getAllIds(), $bundleProduct); + + foreach ($selections as $link) { + $link->setSelectionCanChangeQty(1); + } + + $bundleProduct->setBundleOptionsData([]); + $bundleProduct->setBundleSelectionsData([]); + $this->productRepository->save($bundleProduct); + + $this->assertTrue( + $bundleProduct->isSalable(), + 'Bundle product supposed to be saleable if all his selections have selection_can_change_qty = 1' + ); + } + + private function setQtyForSelections($productsSku, $qty) + { + foreach ($productsSku as $productSku) { + $product = $this->productRepository->get($productSku, false, null, true); + $ea = $product->getExtensionAttributes(); + $ea->getStockItem()->setQty($qty); + $this->productRepository->save($product); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php new file mode 100644 index 0000000000000..5e96221737241 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php @@ -0,0 +1,210 @@ +create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + +/** @var $product \Magento\Catalog\Model\Product */ +$product = $objectManager->create(\Magento\Catalog\Model\Product::class); +$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) + ->setId(3) + ->setAttributeSetId(4) + ->setWebsiteIds([1]) + ->setName('Bundle Product') + ->setSku('bundle-product') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(1) + ->setPriceType(1) + ->setPrice(10.0) + ->setShipmentType(0) + ->setBundleOptionsData( + [ + // Required "Drop-down" option + [ + 'title' => 'Option 1', + 'default_title' => 'Option 1', + 'type' => 'select', + 'required' => 1, + 'delete' => '', + ], + // Required "Radio Buttons" option + [ + 'title' => 'Option 2', + 'default_title' => 'Option 2', + 'type' => 'radio', + 'required' => 1, + 'delete' => '', + ], + // Required "Checkbox" option + [ + 'title' => 'Option 3', + 'default_title' => 'Option 3', + 'type' => 'checkbox', + 'required' => 1, + 'delete' => '', + ], + // Required "Multiple Select" option + [ + 'title' => 'Option 4', + 'default_title' => 'Option 4', + 'type' => 'multi', + 'required' => 1, + 'delete' => '', + ], + // Non-required "Multiple Select" option + [ + 'title' => 'Option 5', + 'default_title' => 'Option 5', + 'type' => 'multi', + 'required' => 0, + 'delete' => '', + ] + ] + )->setBundleSelectionsData( + [ + [ + [ + 'product_id' => 10, + 'selection_qty' => 10, + 'selection_can_change_qty' => 0, + 'delete' => '', + 'option_id' => 1 + ], + [ + 'product_id' => 11, + 'selection_qty' => 10, + 'selection_can_change_qty' => 0, + 'delete' => '', + 'option_id' => 1 + ], + [ + 'product_id' => 12, + 'selection_qty' => 10, + 'selection_can_change_qty' => 0, + 'delete' => '', + 'option_id' => 1 + ] + ], + [ + [ + 'product_id' => 10, + 'selection_qty' => 10, + 'selection_can_change_qty' => 0, + 'delete' => '', + 'option_id' => 2 + ], + [ + 'product_id' => 11, + 'selection_qty' => 10, + 'selection_can_change_qty' => 0, + 'delete' => '', + 'option_id' => 2 + ], + [ + 'product_id' => 13, + 'selection_qty' => 10, + 'selection_can_change_qty' => 0, + 'delete' => '', + 'option_id' => 2 + ] + ], + [ + [ + 'product_id' => 10, + 'selection_qty' => 10, + 'delete' => '', + 'option_id' => 3 + ], + [ + 'product_id' => 11, + 'selection_qty' => 10, + 'delete' => '', + 'option_id' => 3 + ], + [ + 'product_id' => 14, + 'selection_qty' => 10, + 'selection_can_change_qty' => 0, + 'delete' => '', + 'option_id' => 3 + ] + ], + [ + [ + 'product_id' => 13, + 'selection_qty' => 10, + 'delete' => '', + 'option_id' => 4 + ], + [ + 'product_id' => 14, + 'selection_qty' => 10, + 'delete' => '', + 'option_id' => 4 + ], + [ + 'product_id' => 12, + 'selection_qty' => 10, + 'selection_can_change_qty' => 0, + 'delete' => '', + 'option_id' => 4 + ] + ], + [ + [ + 'product_id' => 10, + 'selection_qty' => 10, + 'delete' => '', + 'option_id' => 5 + ], + [ + 'product_id' => 11, + 'selection_qty' => 10, + 'delete' => '', + 'option_id' => 5 + ] + ] + ] + ); + +if ($product->getBundleOptionsData()) { + $options = []; + foreach ($product->getBundleOptionsData() as $key => $optionData) { + if (!(bool)$optionData['delete']) { + $option = $objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) + ->create(['data' => $optionData]); + $option->setSku($product->getSku()); + $option->setOptionId(null); + + $links = []; + $bundleLinks = $product->getBundleSelectionsData(); + if (!empty($bundleLinks[$key])) { + foreach ($bundleLinks[$key] as $linkData) { + if (!(bool)$linkData['delete']) { + $link = $objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) + ->create(['data' => $linkData]); + $linkProduct = $productRepository->getById($linkData['product_id']); + $link->setSku($linkProduct->getSku()); + $link->setQty($linkData['selection_qty']); + $links[] = $link; + } + } + $option->setProductLinks($links); + $options[] = $option; + } + } + } + $extension = $product->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $product->setExtensionAttributes($extension); +} + +$productRepository->save($product, true); \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product_rollback.php new file mode 100644 index 0000000000000..f65dbbbb5435b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product_rollback.php @@ -0,0 +1,27 @@ +get(\Magento\Framework\Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var $product \Magento\Catalog\Model\Product */ +$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product'); + $productRepository->delete($product); +} catch (\Magento\Framework\Exception\NoSuchEntityException $exception) { + //Product already removed +} + + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php new file mode 100644 index 0000000000000..04def919e6aa7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php @@ -0,0 +1,128 @@ +create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + +/** @var $product \Magento\Catalog\Model\Product */ +$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); +$product->isObjectNew(true); +$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) + ->setId(10) + ->setAttributeSetId(4) + ->setName('Simple Product') + ->setSku('simple1') + ->setTaxClassId('none') + ->setDescription('description') + ->setShortDescription('short description') + ->setOptionsContainer('container1') + ->setMsrpDisplayActualPriceType(\Magento\Msrp\Model\Product\Attribute\Source\Type::TYPE_IN_CART) + ->setPrice(10) + ->setWeight(1) + ->setMetaTitle('meta title') + ->setMetaKeyword('meta keyword') + ->setMetaDescription('meta description') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setWebsiteIds([1]) + ->setCateroryIds([]) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]); + +$productRepository->save($product); + +$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); +$product->isObjectNew(true); +$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) + ->setId(11) + ->setAttributeSetId(4) + ->setName('Simple Product2') + ->setSku('simple2') + ->setTaxClassId('none') + ->setDescription('description') + ->setShortDescription('short description') + ->setOptionsContainer('container1') + ->setMsrpDisplayActualPriceType(\Magento\Msrp\Model\Product\Attribute\Source\Type::TYPE_ON_GESTURE) + ->setPrice(20) + ->setWeight(1) + ->setMetaTitle('meta title') + ->setMetaKeyword('meta keyword') + ->setMetaDescription('meta description') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_IN_CATALOG) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setWebsiteIds([1]) + ->setCateroryIds([]) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 50, 'is_qty_decimal' => 0, 'is_in_stock' => 1]); + +$productRepository->save($product); + +$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); +$product->isObjectNew(true); +$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) + ->setId(12) + ->setAttributeSetId(4) + ->setName('Simple Product 3') + ->setSku('simple3') + ->setTaxClassId('none') + ->setDescription('description') + ->setShortDescription('short description') + ->setPrice(30) + ->setWeight(1) + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_IN_CATALOG) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setWebsiteIds([1]) + ->setCateroryIds([]) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 140, 'is_qty_decimal' => 0, 'is_in_stock' => 1]); + +$productRepository->save($product); + +$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); +$product->isObjectNew(true); +$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) + ->setId(13) + ->setAttributeSetId(4) + ->setName('Simple Product 4') + ->setSku('simple4') + ->setTaxClassId('none') + ->setDescription('description') + ->setShortDescription('short description') + ->setOptionsContainer('container1') + ->setMsrpDisplayActualPriceType(\Magento\Msrp\Model\Product\Attribute\Source\Type::TYPE_IN_CART) + ->setPrice(13) + ->setWeight(12) + ->setMetaTitle('meta title') + ->setMetaKeyword('meta keyword') + ->setMetaDescription('meta description') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setWebsiteIds([1]) + ->setCateroryIds([]) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 20, 'is_qty_decimal' => 0, 'is_in_stock' => 1]); + +$productRepository->save($product); + +$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); +$product->isObjectNew(true); +$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) + ->setId(14) + ->setAttributeSetId(4) + ->setName('Simple Product 5') + ->setSku('simple5') + ->setTaxClassId('none') + ->setDescription('description') + ->setShortDescription('short description') + ->setOptionsContainer('container1') + ->setMsrpDisplayActualPriceType(\Magento\Msrp\Model\Product\Attribute\Source\Type::TYPE_IN_CART) + ->setPrice(14) + ->setWeight(10) + ->setMetaTitle('meta title') + ->setMetaKeyword('meta keyword') + ->setMetaDescription('meta description') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setWebsiteIds([1]) + ->setCateroryIds([]) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 15, 'is_qty_decimal' => 0, 'is_in_stock' => 1]); + +$productRepository->save($product); \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products_rollback.php new file mode 100644 index 0000000000000..c13f33bcbf7bb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products_rollback.php @@ -0,0 +1,28 @@ +get(\Magento\Framework\Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + +foreach (['simple1', 'simple2', 'simple3', 'simple4', 'simple5'] as $sku) { + try { + $product = $productRepository->get($sku, false, null, true); + $productRepository->delete($product); + } catch (\Magento\Framework\Exception\NoSuchEntityException $exception) { + //Product already removed + } +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); From 306c01898f5baa078c490f64f0993f6a0e17be65 Mon Sep 17 00:00:00 2001 From: Michail Slabko Date: Wed, 26 Oct 2016 15:45:39 +0300 Subject: [PATCH 017/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-60106: Bundle from-to price calculation is wrong --- app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php index e8d09144a42c5..b64494ab40000 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php @@ -202,7 +202,7 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR $priceList[] = $this->selectionFactory->create( $bundleProduct, $selection, - $bundleProduct->getSelectionQty(), + $selection->getSelectionQty(), [ 'useRegularPrice' => $useRegularPrice, ] @@ -218,11 +218,11 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR $selectionsCollection->addAttributeToSelect('tax_class_id'); $selectionsCollection->addTierPriceData(); } - $selection = $selectionsCollection->getFirstItem(); + $selection = $selectionsCollection->fetchItem(); $priceList[] = $this->selectionFactory->create( $bundleProduct, $selection, - $bundleProduct->getSelectionQty(), + $selection->getSelectionQty(), [ 'useRegularPrice' => $useRegularPrice, ] From 7d3848378d829d04ef0602ec1bcfa7308e381a2a Mon Sep 17 00:00:00 2001 From: Michail Slabko Date: Wed, 26 Oct 2016 17:33:57 +0300 Subject: [PATCH 018/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-60106: Bundle from-to price calculation is wrong --- .../Magento/Bundle/Model/ResourceModel/Selection/Collection.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php index 024ed090efe4b..4aff7c14c7efa 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php @@ -274,6 +274,7 @@ public function addPriceFilter($product, $searchMin, $useRegularPrice = false) $orderByValue = new \Zend_Db_Expr('('. $price. ' * '. 'selection.selection_qty)'); } + $this->getSelect()->reset(Select::ORDER); $this->getSelect()->order($orderByValue . ($searchMin ? Select::SQL_ASC : Select::SQL_DESC)); $this->getSelect()->limit(1); return $this; From 1bb24935c4d3c3c7f639ae8862ccf34b9f397f6d Mon Sep 17 00:00:00 2001 From: Goncharenko Vitaliy Date: Thu, 27 Oct 2016 14:52:35 +0300 Subject: [PATCH 019/161] MAGETWO-53583: "Use Default" checkbox is checked again after saving empty fields (description, name, etc) --- .../Entity/Attribute/AbstractAttribute.php | 58 +++- .../Eav/Model/ResourceModel/UpdateHandler.php | 97 ++++--- .../view/base/web/js/form/element/wysiwyg.js | 2 +- .../Catalog/_files/dropdown_attribute.php | 59 ++++ .../Model/ResourceModel/UpdateHandlerTest.php | 261 ++++++++++++++++++ 5 files changed, 420 insertions(+), 57 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/dropdown_attribute.php create mode 100644 dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index 0d8d18df22376..cad428b2820f4 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -111,6 +111,13 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens */ protected $dataObjectHelper; + /** + * Array of attribute types that have empty string as a possible value. + * + * @var array + */ + private $emptyStringTypes = ['int', 'decimal', 'datetime', 'varchar', 'text', 'static']; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -587,19 +594,44 @@ protected function _getDefaultSourceModel() return $this->getEntityType()->getEntity()->getDefaultAttributeSourceModel(); } - /** - * @param array|null|bool|int|float|string $value - * @return bool - */ - public function isValueEmpty($value) - { - /** @var array $emptyStringTypes list of attribute types that treat empty string as a possible value */ - $emptyStringTypes = ['int', 'decimal', 'datetime', 'varchar', 'text', 'static']; - return (is_array($value) && count($value) == 0) - || $value === null - || ($value === false && $this->getBackend()->getType() != 'int') - || ($value === '' && in_array($this->getBackend()->getType(), $emptyStringTypes)); - } + /** + * Check if Value is empty. + * + * @param array|null|bool|int|float|string $value + * @param bool $strictEmptyStringType [optional] Flag for allow empty string as a possible value for String. + * By default set to TRUE = disallow empty string. + * @return bool + */ + public function isValueEmpty($value, $strictEmptyStringType = true) + { + $isInEmptyStringTypes = $strictEmptyStringType ? $this->isInEmptyStringTypes() : !$this->isInEmptyStringTypes(); + + return (is_array($value) && count($value) == 0) + || $value === null + || ($value === false && $this->getBackend()->getType() != 'int') + || ($value === '' && $isInEmptyStringTypes); + } + + /** + * Check if attribute empty value is valid. + * + * @param array|null|bool|int|float|string $value + * @return bool + */ + public function isAllowedEmptyTextValue($value) + { + return $this->isInEmptyStringTypes() && $value === ''; + } + + /** + * Check is attribute type in allowed empty string types. + * + * @return bool + */ + private function isInEmptyStringTypes() + { + return in_array($this->getBackendType(), $this->emptyStringTypes); + } /** * Check if attribute in specified set diff --git a/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php b/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php index c775a24a03c46..f974760b7b14b 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php +++ b/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php @@ -128,49 +128,60 @@ public function execute($entityType, $entityData, $arguments = []) if ($attribute->isStatic()) { continue; } - /** - * Only scalar values can be stored in generic tables - */ - if (isset($entityData[$attribute->getAttributeCode()]) - && !is_scalar($entityData[$attribute->getAttributeCode()])) { - continue; - } - if (isset($snapshot[$attribute->getAttributeCode()]) - && $snapshot[$attribute->getAttributeCode()] !== false - && (array_key_exists($attribute->getAttributeCode(), $entityData) - && $attribute->isValueEmpty($entityData[$attribute->getAttributeCode()])) - ) { - $this->attributePersistor->registerDelete( - $entityType, - $entityData[$metadata->getLinkField()], - $attribute->getAttributeCode() - ); - } - if ((!array_key_exists($attribute->getAttributeCode(), $snapshot) - || $snapshot[$attribute->getAttributeCode()] === false) - && array_key_exists($attribute->getAttributeCode(), $entityData) - && !$attribute->isValueEmpty($entityData[$attribute->getAttributeCode()]) - ) { - $this->attributePersistor->registerInsert( - $entityType, - $entityData[$metadata->getLinkField()], - $attribute->getAttributeCode(), - $entityData[$attribute->getAttributeCode()] - ); - } - if (array_key_exists($attribute->getAttributeCode(), $snapshot) - && $snapshot[$attribute->getAttributeCode()] !== false - && array_key_exists($attribute->getAttributeCode(), $entityData) - && $snapshot[$attribute->getAttributeCode()] != $entityData[$attribute->getAttributeCode()] - && !$attribute->isValueEmpty($entityData[$attribute->getAttributeCode()]) - ) { - $this->attributePersistor->registerUpdate( - $entityType, - $entityData[$metadata->getLinkField()], - $attribute->getAttributeCode(), - $entityData[$attribute->getAttributeCode()] - ); - } + $code = $attribute->getAttributeCode(); + /** + * Only scalar values can be stored in generic tables + */ + if (isset($entityData[$code]) && !is_scalar($entityData[$code])) { + continue; + } + /** + * Only changed attributes need to handle update process + */ + if (!array_key_exists($code, $entityData)) { + continue; + } + + $newValue = $entityData[$code]; + $isValueEmpty = $attribute->isValueEmpty($newValue, false); + $isAllowedEmptyTextValue = $attribute->isAllowedEmptyTextValue($newValue); + + if (array_key_exists($code, $snapshot)) { + $snapshotValue = $snapshot[$code]; + /** + * 'FALSE' value for attributes can't be update or delete + */ + if ($snapshotValue === false) { + continue; + } + + if ($isValueEmpty && !$isAllowedEmptyTextValue) { + $this->attributePersistor->registerDelete( + $entityType, + $entityData[$metadata->getLinkField()], + $code + ); + } elseif ((!$isValueEmpty || $isAllowedEmptyTextValue) && $snapshotValue !== $newValue) { + $this->attributePersistor->registerUpdate( + $entityType, + $entityData[$metadata->getLinkField()], + $code, + $newValue + ); + } + } else { + /** + * Only not empty value of attribute is insertable + */ + if (!$isValueEmpty || $isAllowedEmptyTextValue) { + $this->attributePersistor->registerInsert( + $entityType, + $entityData[$metadata->getLinkField()], + $code, + $newValue + ); + } + } } $this->attributePersistor->flush($entityType, $context); } diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js b/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js index 01c8ef29029a9..209b05773a497 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js @@ -93,7 +93,7 @@ define([ /* eslint-disable no-undef */ if (tinyMCE) { _.each(tinyMCE.activeEditor.controlManager.controls, function (property, index, controls) { - controls[property].setDisabled(status); + controls[property.id].setDisabled(status); }); tinyMCE.activeEditor.getBody().setAttribute('contenteditable', !status); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/dropdown_attribute.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/dropdown_attribute.php new file mode 100644 index 0000000000000..fcd770f4418ae --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/dropdown_attribute.php @@ -0,0 +1,59 @@ +create( + \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class +); + +if (!$attribute->loadByCode(4, 'dropdown_attribute')->getId()) { + /** @var $installer \Magento\Catalog\Setup\CategorySetup */ + $installer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Setup\CategorySetup::class + ); + + $attribute->setData( + [ + 'attribute_code' => 'dropdown_attribute', + 'entity_type_id' => $installer->getEntityTypeId('catalog_product'), + 'is_global' => 0, + 'is_user_defined' => 1, + 'frontend_input' => 'select', + 'is_unique' => 0, + 'is_required' => 0, + 'is_searchable' => 0, + 'is_visible_in_advanced_search' => 0, + 'is_comparable' => 0, + 'is_filterable' => 0, + 'is_filterable_in_search' => 0, + 'is_used_for_promo_rules' => 0, + 'is_html_allowed_on_front' => 1, + 'is_visible_on_front' => 0, + 'used_in_product_listing' => 0, + 'used_for_sort_by' => 0, + 'frontend_label' => ['Drop-Down Attribute'], + 'backend_type' => 'varchar', + 'backend_model' => \Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend::class, + 'option' => [ + 'value' => [ + 'option_1' => ['Option 1'], + 'option_2' => ['Option 2'], + 'option_3' => ['Option 3'], + ], + 'order' => [ + 'option_1' => 1, + 'option_2' => 2, + 'option_3' => 3, + ], + ], + ] + ); + $attribute->save(); + + /* Assign attribute to attribute set */ + $installer->addAttributeToGroup('catalog_product', 'Default', 'Attributes', $attribute->getId()); +} diff --git a/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php b/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php new file mode 100644 index 0000000000000..ce5d348134be0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php @@ -0,0 +1,261 @@ +create(\Magento\Catalog\Model\Product::class); + $entity->setStoreId(0); + $entity->load(1); + $entity->setData($code, $snapshotValue); + $entity->save(); + } + + $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $entity->setStoreId(0); + $entity->load(1); + + $updateHandler = Bootstrap::getObjectManager()->create(UpdateHandler::class); + $entityData = array_merge($entity->getData(), [$code => $newValue]); + $updateHandler->execute('Magento\Catalog\Api\Data\ProductInterface', $entityData); + + $resultEntity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $resultEntity->setStoreId(0); + $resultEntity->load(1); + + $this->assertTrue($expected === $resultEntity->getData($code)); + } + + /** + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + * @covers \Magento\Eav\Model\ResourceModel\UpdateHandlerTest::execute + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @magentoDataFixture Magento/Store/_files/second_store.php + * @dataProvider getCustomStoreDataProvider + * @param $code + * @param $snapshotValue + * @param $newValue + * @param $expected + */ + public function testExecuteProcessForCustomStore($code, $snapshotValue, $newValue, $expected) + { + $store = Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class); + $store->load('fixture_second_store', 'code'); + + Bootstrap::getObjectManager() + ->create(\Magento\CatalogSearch\Model\Indexer\Fulltext\Processor::class) + ->reindexAll(); + + if ($snapshotValue !== '-') { + $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $entity->setStoreId($store->getId()); + $entity->load(1); + $entity->setData($code, $snapshotValue); + $entity->save(); + } + + $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $entity->setStoreId($store->getId()); + $entity->load(1); + + $updateHandler = Bootstrap::getObjectManager()->create(UpdateHandler::class); + $entityData = array_merge($entity->getData(), [$code => $newValue]); + $updateHandler->execute('Magento\Catalog\Api\Data\ProductInterface', $entityData); + + $resultEntity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $resultEntity->setStoreId($store->getId()); + $resultEntity->load(1); + + $this->assertTrue($expected === $resultEntity->getData($code)); + } + + /** + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + * @covers \Magento\Eav\Model\ResourceModel\UpdateHandlerTest::execute + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @magentoDataFixture Magento/Catalog/_files/dropdown_attribute.php + * @magentoDataFixture Magento/Store/_files/second_store.php + * @dataProvider getCustomAttributeDataProvider + * @param $code + * @param $defaultStoreValue + * @param $snapshotValue + * @param $newValue + * @param $expected + */ + public function testExecuteProcessForCustomAttributeInCustomStore( + $code, + $defaultStoreValue, + $snapshotValue, + $newValue, + $expected + ) { + $store = Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class); + $store->load('fixture_second_store', 'code'); + + Bootstrap::getObjectManager() + ->create(\Magento\CatalogSearch\Model\Indexer\Fulltext\Processor::class) + ->reindexAll(); + + $attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class + ); + $attribute->loadByCode(4, $code); + + $options = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection::class + ); + $options->setAttributeFilter($attribute->getId()); + $optionIds = $options->getAllIds(); + + $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $entity->setStoreId(0); + $entity->load(1); + $entity->setData($code, $optionIds[$defaultStoreValue]); + $entity->save(); + + if ($snapshotValue !== '-') { + /** @var $options \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection */ + $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $entity->setStoreId($store->getId()); + $entity->load(1); + + if ($snapshotValue) { + $snapshotValue = $optionIds[$snapshotValue]; + } + + $entity->setData($code, $snapshotValue); + $entity->save(); + } + + $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $entity->setStoreId($store->getId()); + $entity->load(1); + + $updateHandler = Bootstrap::getObjectManager()->create(UpdateHandler::class); + + if ($newValue) { + $newValue = $optionIds[$newValue]; + } + + $entityData = array_merge($entity->getData(), [$code => $newValue]); + $updateHandler->execute('Magento\Catalog\Api\Data\ProductInterface', $entityData); + + $resultEntity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $resultEntity->setStoreId($store->getId()); + $resultEntity->load(1); + + if ($expected !== null) { + $expected = $optionIds[$expected]; + } + + $this->assertTrue($expected === $resultEntity->getData($code)); + } + + /** + * @return array + */ + public function getAllStoresDataProvider() + { + return [ + ['description', '', 'not_empty_value', 'not_empty_value'], //0 + ['description', '', '', null], //1 + ['description', '', null, null], //2 + ['description', '', false, null], //3 + + ['description', 'not_empty_value', 'not_empty_value2', 'not_empty_value2'],//4 + ['description', 'not_empty_value', '', null], //5 + ['description', 'not_empty_value', null, null], //6 + ['description', 'not_empty_value', false, null], //7 + + ['description', null, 'not_empty_value', 'not_empty_value'], //8 + ['description', null, '', null], //9 + ['description', null, false, null], //10 + + ['description', false, 'not_empty_value', 'not_empty_value'], //11 + ['description', false, '', null], //12 + ['description', false, null, null], //13 + ]; + } + + /** + * @return array + */ + public function getCustomStoreDataProvider() + { + return [ + ['description', '', 'not_empty_value', 'not_empty_value'], //0 + ['description', '', '', null], //1 + ['description', '', null, 'Description with html tag'], //2 + ['description', '', false, 'Description with html tag'], //3 + + ['description', 'not_empty_value', 'not_empty_value2', 'not_empty_value2'], //4 + ['description', 'not_empty_value', '', null], //5 + ['description', 'not_empty_value', null, 'Description with html tag'], //6 + ['description', 'not_empty_value', false, 'Description with html tag'], //7 + + ['description', null, 'not_empty_value', 'not_empty_value'], //8 + ['description', null, '', null], //9 + ['description', null, false, 'Description with html tag'], //10 + + ['description', false, 'not_empty_value', 'not_empty_value'], //11 + ['description', false, '', null], //12 + ['description', false, null, 'Description with html tag'], //13 + ]; + } + + /** + * @return array + */ + public function getCustomAttributeDataProvider() + { + return [ + ['dropdown_attribute', 0, '', 1, 1], //0 + ['dropdown_attribute', 0, '', '', null], //1 + ['dropdown_attribute', 0, '', null, 0], //2 + ['dropdown_attribute', 0, '', false, 0], //3 + + ['dropdown_attribute', 0, 1, 2, 2], //4 + ['dropdown_attribute', 0, 1, '', null], //5 + ['dropdown_attribute', 0, 1, null, 0], //6 + ['dropdown_attribute', 0, 1, false, 0], //7 + + ['dropdown_attribute', 0, null, 1, 1], //8 + ['dropdown_attribute', 0, null, '', null], //9 + ['dropdown_attribute', 0, null, false, 0], //10 + + ['dropdown_attribute', 0, false, 1, 1], //11 + ['dropdown_attribute', 0, false, '', null], //12 + ['dropdown_attribute', 0, false, null, 0], //13 + + ['dropdown_attribute', 0, '-', 1, 1], //14 + ['dropdown_attribute', 0, '-', '', null], //15 + ['dropdown_attribute', 0, '-', null, 0], //16 + ['dropdown_attribute', 0, '-', false, 0], //17 + ]; + } +} From 00ad9ac5fb8a0abfb854b5d493bb771821864467 Mon Sep 17 00:00:00 2001 From: Vitaliy Goncharenko Date: Thu, 27 Oct 2016 18:50:56 +0300 Subject: [PATCH 020/161] MAGETWO-53583: "Use Default" checkbox is checked again after saving empty fields (description, name, etc) - fixed static --- .../Entity/Attribute/AbstractAttribute.php | 198 +++---- .../Eav/Model/ResourceModel/UpdateHandler.php | 110 ++-- .../Catalog/_files/dropdown_attribute.php | 86 +-- .../Model/ResourceModel/UpdateHandlerTest.php | 490 +++++++++--------- 4 files changed, 452 insertions(+), 432 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index cad428b2820f4..2804250a35c6e 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -111,12 +111,12 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens */ protected $dataObjectHelper; - /** - * Array of attribute types that have empty string as a possible value. - * - * @var array - */ - private $emptyStringTypes = ['int', 'decimal', 'datetime', 'varchar', 'text', 'static']; + /** + * Array of attribute types that have empty string as a possible value. + * + * @var array + */ + private $emptyStringTypes = ['int', 'decimal', 'datetime', 'varchar', 'text', 'static']; /** * @param \Magento\Framework\Model\Context $context @@ -209,6 +209,7 @@ public function loadByCode($entityType, $code) $this->_getResource()->loadByCode($this, $entityTypeId, $code); $this->_afterLoad(); \Magento\Framework\Profiler::stop('load_by_code'); + return $this; } @@ -233,6 +234,7 @@ public function getName() public function setAttributeId($data) { $this->_data['attribute_id'] = $data; + return $this; } @@ -379,6 +381,7 @@ public function getAttributeSetId() public function setAttributeSetId($id) { $this->_data['attribute_set_id'] = $id; + return $this; } @@ -399,6 +402,7 @@ public function getEntityTypeId() public function setEntityTypeId($id) { $this->_data['entity_type_id'] = $id; + return $this; } @@ -410,6 +414,7 @@ public function setEntityTypeId($id) public function setEntityType($type) { $this->setData('entity_type', $type); + return $this; } @@ -463,6 +468,7 @@ public function getEntityType() public function setEntity($entity) { $this->_entity = $entity; + return $this; } @@ -476,6 +482,7 @@ public function getEntity() if (!$this->_entity) { $this->_entity = $this->getEntityType(); } + return $this->_entity; } @@ -553,6 +560,7 @@ public function getSource() } $this->_source = $source->setAttribute($this); } + return $this->_source; } @@ -564,6 +572,7 @@ public function getSource() public function usesSource() { $input = $this->getFrontendInput(); + return $input === 'select' || $input === 'multiselect' || $this->_getData('source_model') != ''; } @@ -594,44 +603,44 @@ protected function _getDefaultSourceModel() return $this->getEntityType()->getEntity()->getDefaultAttributeSourceModel(); } - /** - * Check if Value is empty. - * - * @param array|null|bool|int|float|string $value - * @param bool $strictEmptyStringType [optional] Flag for allow empty string as a possible value for String. - * By default set to TRUE = disallow empty string. - * @return bool - */ - public function isValueEmpty($value, $strictEmptyStringType = true) - { - $isInEmptyStringTypes = $strictEmptyStringType ? $this->isInEmptyStringTypes() : !$this->isInEmptyStringTypes(); - - return (is_array($value) && count($value) == 0) - || $value === null - || ($value === false && $this->getBackend()->getType() != 'int') - || ($value === '' && $isInEmptyStringTypes); - } - - /** - * Check if attribute empty value is valid. - * - * @param array|null|bool|int|float|string $value - * @return bool - */ - public function isAllowedEmptyTextValue($value) - { - return $this->isInEmptyStringTypes() && $value === ''; - } - - /** - * Check is attribute type in allowed empty string types. - * - * @return bool - */ - private function isInEmptyStringTypes() - { - return in_array($this->getBackendType(), $this->emptyStringTypes); - } + /** + * Check if Value is empty. + * + * @param array|null|bool|int|float|string $value + * @param bool $strictEmptyStringType [optional] Flag for allow empty string as a possible value for String. + * By default set to TRUE = disallow empty string. + * @return bool + */ + public function isValueEmpty($value, $strictEmptyStringType = true) + { + $isInEmptyStringTypes = $strictEmptyStringType ? $this->isInEmptyStringTypes() : !$this->isInEmptyStringTypes(); + + return (is_array($value) && count($value) == 0) + || $value === null + || ($value === false && $this->getBackend()->getType() != 'int') + || ($value === '' && $isInEmptyStringTypes); + } + + /** + * Check if attribute empty value is valid. + * + * @param array|null|bool|int|float|string $value + * @return bool + */ + public function isAllowedEmptyTextValue($value) + { + return $this->isInEmptyStringTypes() && $value === ''; + } + + /** + * Check is attribute type in allowed empty string types. + * + * @return bool + */ + private function isInEmptyStringTypes() + { + return in_array($this->getBackend()->getType(), $this->emptyStringTypes); + } /** * Check if attribute in specified set @@ -686,6 +695,7 @@ public function getIdByCode($entityType, $code) if (!isset($this->_attributeIdCache[$cacheKey])) { $this->_attributeIdCache[$cacheKey] = $this->getResource()->getIdByCode($entityType, $code); } + return $this->_attributeIdCache[$cacheKey]; } @@ -718,6 +728,7 @@ public function getBackendTable() $this->_dataTable = $backendTable; } } + return $this->_dataTable; } @@ -732,6 +743,7 @@ public function getFlatColumns() if ($this->usesSource() && $this->getBackendType() != self::TYPE_STATIC) { return $this->getSource()->getFlatColumns(); } + return $this->_getFlatColumnsDdlDefinition(); } @@ -755,60 +767,60 @@ public function _getFlatColumnsDdlDefinition() $size = $prop['LENGTH'] ? $prop['LENGTH'] : null; $columns[$this->getAttributeCode()] = [ - 'type' => $this->_resourceHelper->getDdlTypeByColumnType($type), - 'length' => $size, + 'type' => $this->_resourceHelper->getDdlTypeByColumnType($type), + 'length' => $size, 'unsigned' => $prop['UNSIGNED'] ? true : false, 'nullable' => $prop['NULLABLE'], - 'default' => $prop['DEFAULT'], - 'extra' => null, + 'default' => $prop['DEFAULT'], + 'extra' => null, ]; break; case 'datetime': $columns[$this->getAttributeCode()] = [ - 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_DATETIME, + 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_DATETIME, 'unsigned' => false, 'nullable' => true, - 'default' => null, - 'extra' => null, + 'default' => null, + 'extra' => null, ]; break; case 'decimal': $columns[$this->getAttributeCode()] = [ - 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, - 'length' => '12,4', + 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, + 'length' => '12,4', 'unsigned' => false, 'nullable' => true, - 'default' => null, - 'extra' => null, + 'default' => null, + 'extra' => null, ]; break; case 'int': $columns[$this->getAttributeCode()] = [ - 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 'unsigned' => false, 'nullable' => true, - 'default' => null, - 'extra' => null, + 'default' => null, + 'extra' => null, ]; break; case 'text': $columns[$this->getAttributeCode()] = [ - 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 'unsigned' => false, 'nullable' => true, - 'default' => null, - 'extra' => null, - 'length' => \Magento\Framework\DB\Ddl\Table::MAX_TEXT_SIZE, + 'default' => null, + 'extra' => null, + 'length' => \Magento\Framework\DB\Ddl\Table::MAX_TEXT_SIZE, ]; break; case 'varchar': $columns[$this->getAttributeCode()] = [ - 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 'length' => '255', + 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 'length' => '255', 'unsigned' => false, 'nullable' => true, - 'default' => null, - 'extra' => null, + 'default' => null, + 'extra' => null, ]; break; default: @@ -836,61 +848,62 @@ protected function _getFlatColumnsOldDefinition() } $prop = $describe[$this->getAttributeCode()]; $columns[$this->getAttributeCode()] = [ - 'type' => $prop['DATA_TYPE'] . ($prop['LENGTH'] ? "({$prop['LENGTH']})" : ""), + 'type' => $prop['DATA_TYPE'] . ($prop['LENGTH'] ? "({$prop['LENGTH']})" : ""), 'unsigned' => $prop['UNSIGNED'] ? true : false, - 'is_null' => $prop['NULLABLE'], - 'default' => $prop['DEFAULT'], - 'extra' => null, + 'is_null' => $prop['NULLABLE'], + 'default' => $prop['DEFAULT'], + 'extra' => null, ]; break; case 'datetime': $columns[$this->getAttributeCode()] = [ - 'type' => 'datetime', + 'type' => 'datetime', 'unsigned' => false, - 'is_null' => true, - 'default' => null, - 'extra' => null, + 'is_null' => true, + 'default' => null, + 'extra' => null, ]; break; case 'decimal': $columns[$this->getAttributeCode()] = [ - 'type' => 'decimal(12,4)', + 'type' => 'decimal(12,4)', 'unsigned' => false, - 'is_null' => true, - 'default' => null, - 'extra' => null, + 'is_null' => true, + 'default' => null, + 'extra' => null, ]; break; case 'int': $columns[$this->getAttributeCode()] = [ - 'type' => 'int', + 'type' => 'int', 'unsigned' => false, - 'is_null' => true, - 'default' => null, - 'extra' => null, + 'is_null' => true, + 'default' => null, + 'extra' => null, ]; break; case 'text': $columns[$this->getAttributeCode()] = [ - 'type' => 'text', + 'type' => 'text', 'unsigned' => false, - 'is_null' => true, - 'default' => null, - 'extra' => null, + 'is_null' => true, + 'default' => null, + 'extra' => null, ]; break; case 'varchar': $columns[$this->getAttributeCode()] = [ - 'type' => 'varchar(255)', + 'type' => 'varchar(255)', 'unsigned' => false, - 'is_null' => true, - 'default' => null, - 'extra' => null, + 'is_null' => true, + 'default' => null, + 'extra' => null, ]; break; default: break; } + return $columns; } @@ -977,6 +990,7 @@ public function getFlatUpdateSelect($store = null) foreach ($this->_storeManager->getStores() as $store) { $this->getFlatUpdateSelect($store->getId()); } + return $this; } @@ -987,6 +1001,7 @@ public function getFlatUpdateSelect($store = null) if ($this->usesSource()) { return $this->getSource()->getFlatUpdateSelect($store); } + return $this->_getResource()->getFlatUpdateSelect($this, $store); } @@ -1096,6 +1111,7 @@ public function setOptions(array $options = null) } else { $this->setData(self::OPTIONS, $options); } + return $this; } @@ -1118,6 +1134,7 @@ protected function convertToObjects(array $options) ); $dataObjects[] = $optionDataObject; } + return $dataObjects; } @@ -1229,6 +1246,7 @@ public function getValidationRules() } elseif (!empty($rules)) { return unserialize($rules); } + return []; } diff --git a/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php b/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php index f974760b7b14b..4494d66b42fc6 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php +++ b/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php @@ -128,63 +128,64 @@ public function execute($entityType, $entityData, $arguments = []) if ($attribute->isStatic()) { continue; } - $code = $attribute->getAttributeCode(); - /** - * Only scalar values can be stored in generic tables - */ - if (isset($entityData[$code]) && !is_scalar($entityData[$code])) { - continue; - } - /** - * Only changed attributes need to handle update process - */ - if (!array_key_exists($code, $entityData)) { - continue; - } - - $newValue = $entityData[$code]; - $isValueEmpty = $attribute->isValueEmpty($newValue, false); - $isAllowedEmptyTextValue = $attribute->isAllowedEmptyTextValue($newValue); - - if (array_key_exists($code, $snapshot)) { - $snapshotValue = $snapshot[$code]; - /** - * 'FALSE' value for attributes can't be update or delete - */ - if ($snapshotValue === false) { - continue; - } - - if ($isValueEmpty && !$isAllowedEmptyTextValue) { - $this->attributePersistor->registerDelete( - $entityType, - $entityData[$metadata->getLinkField()], - $code - ); - } elseif ((!$isValueEmpty || $isAllowedEmptyTextValue) && $snapshotValue !== $newValue) { - $this->attributePersistor->registerUpdate( - $entityType, - $entityData[$metadata->getLinkField()], - $code, - $newValue - ); - } - } else { - /** - * Only not empty value of attribute is insertable - */ - if (!$isValueEmpty || $isAllowedEmptyTextValue) { - $this->attributePersistor->registerInsert( - $entityType, - $entityData[$metadata->getLinkField()], - $code, - $newValue - ); - } - } + $code = $attribute->getAttributeCode(); + /** + * Only scalar values can be stored in generic tables + */ + if (isset($entityData[$code]) && !is_scalar($entityData[$code])) { + continue; + } + /** + * Only changed attributes need to handle update process + */ + if (!array_key_exists($code, $entityData)) { + continue; + } + + $newValue = $entityData[$code]; + $isValueEmpty = $attribute->isValueEmpty($newValue, false); + $isAllowedEmptyTextValue = $attribute->isAllowedEmptyTextValue($newValue); + + if (array_key_exists($code, $snapshot)) { + $snapshotValue = $snapshot[$code]; + /** + * 'FALSE' value for attributes can't be update or delete + */ + if ($snapshotValue === false) { + continue; + } + + if ($isValueEmpty && !$isAllowedEmptyTextValue) { + $this->attributePersistor->registerDelete( + $entityType, + $entityData[$metadata->getLinkField()], + $code + ); + } elseif ((!$isValueEmpty || $isAllowedEmptyTextValue) && $snapshotValue !== $newValue) { + $this->attributePersistor->registerUpdate( + $entityType, + $entityData[$metadata->getLinkField()], + $code, + $newValue + ); + } + } else { + /** + * Only not empty value of attribute is insertable + */ + if (!$isValueEmpty || $isAllowedEmptyTextValue) { + $this->attributePersistor->registerInsert( + $entityType, + $entityData[$metadata->getLinkField()], + $code, + $newValue + ); + } + } } $this->attributePersistor->flush($entityType, $context); } + return $this->getReadHandler()->execute($entityType, $entityData, $arguments); } @@ -200,6 +201,7 @@ protected function getReadHandler() if (!$this->readHandler) { $this->readHandler = ObjectManager::getInstance()->get(ReadHandler::class); } + return $this->readHandler; } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/dropdown_attribute.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/dropdown_attribute.php index fcd770f4418ae..56e84046b255b 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/dropdown_attribute.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/dropdown_attribute.php @@ -11,49 +11,49 @@ ); if (!$attribute->loadByCode(4, 'dropdown_attribute')->getId()) { - /** @var $installer \Magento\Catalog\Setup\CategorySetup */ - $installer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Catalog\Setup\CategorySetup::class - ); + /** @var $installer \Magento\Catalog\Setup\CategorySetup */ + $installer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Setup\CategorySetup::class + ); - $attribute->setData( - [ - 'attribute_code' => 'dropdown_attribute', - 'entity_type_id' => $installer->getEntityTypeId('catalog_product'), - 'is_global' => 0, - 'is_user_defined' => 1, - 'frontend_input' => 'select', - 'is_unique' => 0, - 'is_required' => 0, - 'is_searchable' => 0, - 'is_visible_in_advanced_search' => 0, - 'is_comparable' => 0, - 'is_filterable' => 0, - 'is_filterable_in_search' => 0, - 'is_used_for_promo_rules' => 0, - 'is_html_allowed_on_front' => 1, - 'is_visible_on_front' => 0, - 'used_in_product_listing' => 0, - 'used_for_sort_by' => 0, - 'frontend_label' => ['Drop-Down Attribute'], - 'backend_type' => 'varchar', - 'backend_model' => \Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend::class, - 'option' => [ - 'value' => [ - 'option_1' => ['Option 1'], - 'option_2' => ['Option 2'], - 'option_3' => ['Option 3'], - ], - 'order' => [ - 'option_1' => 1, - 'option_2' => 2, - 'option_3' => 3, - ], - ], - ] - ); - $attribute->save(); + $attribute->setData( + [ + 'attribute_code' => 'dropdown_attribute', + 'entity_type_id' => $installer->getEntityTypeId('catalog_product'), + 'is_global' => 0, + 'is_user_defined' => 1, + 'frontend_input' => 'select', + 'is_unique' => 0, + 'is_required' => 0, + 'is_searchable' => 0, + 'is_visible_in_advanced_search' => 0, + 'is_comparable' => 0, + 'is_filterable' => 0, + 'is_filterable_in_search' => 0, + 'is_used_for_promo_rules' => 0, + 'is_html_allowed_on_front' => 1, + 'is_visible_on_front' => 0, + 'used_in_product_listing' => 0, + 'used_for_sort_by' => 0, + 'frontend_label' => ['Drop-Down Attribute'], + 'backend_type' => 'varchar', + 'backend_model' => \Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend::class, + 'option' => [ + 'value' => [ + 'option_1' => ['Option 1'], + 'option_2' => ['Option 2'], + 'option_3' => ['Option 3'], + ], + 'order' => [ + 'option_1' => 1, + 'option_2' => 2, + 'option_3' => 3, + ], + ], + ] + ); + $attribute->save(); - /* Assign attribute to attribute set */ - $installer->addAttributeToGroup('catalog_product', 'Default', 'Attributes', $attribute->getId()); + /* Assign attribute to attribute set */ + $installer->addAttributeToGroup('catalog_product', 'Default', 'Attributes', $attribute->getId()); } diff --git a/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php b/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php index ce5d348134be0..8851ab0c71eb9 100644 --- a/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php +++ b/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php @@ -13,249 +13,249 @@ */ class UpdateHandlerTest extends \PHPUnit_Framework_TestCase { - /** - * @magentoAppIsolation enabled - * @magentoDbIsolation enabled - * @covers \Magento\Eav\Model\ResourceModel\UpdateHandlerTest::execute - * @magentoDataFixture Magento/Catalog/_files/product_simple.php - * @dataProvider getAllStoresDataProvider - * @param $code - * @param $snapshotValue - * @param $newValue - * @param $expected - */ - public function testExecuteProcessForAllStores($code, $snapshotValue, $newValue, $expected) - { - if ($snapshotValue !== '-') { - $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); - $entity->setStoreId(0); - $entity->load(1); - $entity->setData($code, $snapshotValue); - $entity->save(); - } - - $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); - $entity->setStoreId(0); - $entity->load(1); - - $updateHandler = Bootstrap::getObjectManager()->create(UpdateHandler::class); - $entityData = array_merge($entity->getData(), [$code => $newValue]); - $updateHandler->execute('Magento\Catalog\Api\Data\ProductInterface', $entityData); - - $resultEntity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); - $resultEntity->setStoreId(0); - $resultEntity->load(1); - - $this->assertTrue($expected === $resultEntity->getData($code)); - } - - /** - * @magentoAppIsolation enabled - * @magentoDbIsolation enabled - * @covers \Magento\Eav\Model\ResourceModel\UpdateHandlerTest::execute - * @magentoDataFixture Magento/Catalog/_files/product_simple.php - * @magentoDataFixture Magento/Store/_files/second_store.php - * @dataProvider getCustomStoreDataProvider - * @param $code - * @param $snapshotValue - * @param $newValue - * @param $expected - */ - public function testExecuteProcessForCustomStore($code, $snapshotValue, $newValue, $expected) - { - $store = Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class); - $store->load('fixture_second_store', 'code'); - - Bootstrap::getObjectManager() - ->create(\Magento\CatalogSearch\Model\Indexer\Fulltext\Processor::class) - ->reindexAll(); - - if ($snapshotValue !== '-') { - $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); - $entity->setStoreId($store->getId()); - $entity->load(1); - $entity->setData($code, $snapshotValue); - $entity->save(); - } - - $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); - $entity->setStoreId($store->getId()); - $entity->load(1); - - $updateHandler = Bootstrap::getObjectManager()->create(UpdateHandler::class); - $entityData = array_merge($entity->getData(), [$code => $newValue]); - $updateHandler->execute('Magento\Catalog\Api\Data\ProductInterface', $entityData); - - $resultEntity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); - $resultEntity->setStoreId($store->getId()); - $resultEntity->load(1); - - $this->assertTrue($expected === $resultEntity->getData($code)); - } - - /** - * @magentoAppIsolation enabled - * @magentoDbIsolation enabled - * @covers \Magento\Eav\Model\ResourceModel\UpdateHandlerTest::execute - * @magentoDataFixture Magento/Catalog/_files/product_simple.php - * @magentoDataFixture Magento/Catalog/_files/dropdown_attribute.php - * @magentoDataFixture Magento/Store/_files/second_store.php - * @dataProvider getCustomAttributeDataProvider - * @param $code - * @param $defaultStoreValue - * @param $snapshotValue - * @param $newValue - * @param $expected - */ - public function testExecuteProcessForCustomAttributeInCustomStore( - $code, - $defaultStoreValue, - $snapshotValue, - $newValue, - $expected - ) { - $store = Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class); - $store->load('fixture_second_store', 'code'); - - Bootstrap::getObjectManager() - ->create(\Magento\CatalogSearch\Model\Indexer\Fulltext\Processor::class) - ->reindexAll(); - - $attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class - ); - $attribute->loadByCode(4, $code); - - $options = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection::class - ); - $options->setAttributeFilter($attribute->getId()); - $optionIds = $options->getAllIds(); - - $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); - $entity->setStoreId(0); - $entity->load(1); - $entity->setData($code, $optionIds[$defaultStoreValue]); - $entity->save(); - - if ($snapshotValue !== '-') { - /** @var $options \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection */ - $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); - $entity->setStoreId($store->getId()); - $entity->load(1); - - if ($snapshotValue) { - $snapshotValue = $optionIds[$snapshotValue]; - } - - $entity->setData($code, $snapshotValue); - $entity->save(); - } - - $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); - $entity->setStoreId($store->getId()); - $entity->load(1); - - $updateHandler = Bootstrap::getObjectManager()->create(UpdateHandler::class); - - if ($newValue) { - $newValue = $optionIds[$newValue]; - } - - $entityData = array_merge($entity->getData(), [$code => $newValue]); - $updateHandler->execute('Magento\Catalog\Api\Data\ProductInterface', $entityData); - - $resultEntity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); - $resultEntity->setStoreId($store->getId()); - $resultEntity->load(1); - - if ($expected !== null) { - $expected = $optionIds[$expected]; - } - - $this->assertTrue($expected === $resultEntity->getData($code)); - } - - /** - * @return array - */ - public function getAllStoresDataProvider() - { - return [ - ['description', '', 'not_empty_value', 'not_empty_value'], //0 - ['description', '', '', null], //1 - ['description', '', null, null], //2 - ['description', '', false, null], //3 - - ['description', 'not_empty_value', 'not_empty_value2', 'not_empty_value2'],//4 - ['description', 'not_empty_value', '', null], //5 - ['description', 'not_empty_value', null, null], //6 - ['description', 'not_empty_value', false, null], //7 - - ['description', null, 'not_empty_value', 'not_empty_value'], //8 - ['description', null, '', null], //9 - ['description', null, false, null], //10 - - ['description', false, 'not_empty_value', 'not_empty_value'], //11 - ['description', false, '', null], //12 - ['description', false, null, null], //13 - ]; - } - - /** - * @return array - */ - public function getCustomStoreDataProvider() - { - return [ - ['description', '', 'not_empty_value', 'not_empty_value'], //0 - ['description', '', '', null], //1 - ['description', '', null, 'Description with html tag'], //2 - ['description', '', false, 'Description with html tag'], //3 - - ['description', 'not_empty_value', 'not_empty_value2', 'not_empty_value2'], //4 - ['description', 'not_empty_value', '', null], //5 - ['description', 'not_empty_value', null, 'Description with html tag'], //6 - ['description', 'not_empty_value', false, 'Description with html tag'], //7 - - ['description', null, 'not_empty_value', 'not_empty_value'], //8 - ['description', null, '', null], //9 - ['description', null, false, 'Description with html tag'], //10 - - ['description', false, 'not_empty_value', 'not_empty_value'], //11 - ['description', false, '', null], //12 - ['description', false, null, 'Description with html tag'], //13 - ]; - } - - /** - * @return array - */ - public function getCustomAttributeDataProvider() - { - return [ - ['dropdown_attribute', 0, '', 1, 1], //0 - ['dropdown_attribute', 0, '', '', null], //1 - ['dropdown_attribute', 0, '', null, 0], //2 - ['dropdown_attribute', 0, '', false, 0], //3 - - ['dropdown_attribute', 0, 1, 2, 2], //4 - ['dropdown_attribute', 0, 1, '', null], //5 - ['dropdown_attribute', 0, 1, null, 0], //6 - ['dropdown_attribute', 0, 1, false, 0], //7 - - ['dropdown_attribute', 0, null, 1, 1], //8 - ['dropdown_attribute', 0, null, '', null], //9 - ['dropdown_attribute', 0, null, false, 0], //10 - - ['dropdown_attribute', 0, false, 1, 1], //11 - ['dropdown_attribute', 0, false, '', null], //12 - ['dropdown_attribute', 0, false, null, 0], //13 - - ['dropdown_attribute', 0, '-', 1, 1], //14 - ['dropdown_attribute', 0, '-', '', null], //15 - ['dropdown_attribute', 0, '-', null, 0], //16 - ['dropdown_attribute', 0, '-', false, 0], //17 - ]; - } + /** + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + * @covers \Magento\Eav\Model\ResourceModel\UpdateHandler::execute + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @dataProvider getAllStoresDataProvider + * @param $code + * @param $snapshotValue + * @param $newValue + * @param $expected + */ + public function testExecuteProcessForAllStores($code, $snapshotValue, $newValue, $expected) + { + if ($snapshotValue !== '-') { + $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $entity->setStoreId(0); + $entity->load(1); + $entity->setData($code, $snapshotValue); + $entity->save(); + } + + $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $entity->setStoreId(0); + $entity->load(1); + + $updateHandler = Bootstrap::getObjectManager()->create(UpdateHandler::class); + $entityData = array_merge($entity->getData(), [$code => $newValue]); + $updateHandler->execute(\Magento\Catalog\Api\Data\ProductInterface::class, $entityData); + + $resultEntity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $resultEntity->setStoreId(0); + $resultEntity->load(1); + + $this->assertTrue($expected === $resultEntity->getData($code)); + } + + /** + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + * @covers \Magento\Eav\Model\ResourceModel\UpdateHandlerTest::execute + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @magentoDataFixture Magento/Store/_files/second_store.php + * @dataProvider getCustomStoreDataProvider + * @param $code + * @param $snapshotValue + * @param $newValue + * @param $expected + */ + public function testExecuteProcessForCustomStore($code, $snapshotValue, $newValue, $expected) + { + $store = Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class); + $store->load('fixture_second_store', 'code'); + + Bootstrap::getObjectManager() + ->create(\Magento\CatalogSearch\Model\Indexer\Fulltext\Processor::class) + ->reindexAll(); + + if ($snapshotValue !== '-') { + $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $entity->setStoreId($store->getId()); + $entity->load(1); + $entity->setData($code, $snapshotValue); + $entity->save(); + } + + $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $entity->setStoreId($store->getId()); + $entity->load(1); + + $updateHandler = Bootstrap::getObjectManager()->create(UpdateHandler::class); + $entityData = array_merge($entity->getData(), [$code => $newValue]); + $updateHandler->execute(\Magento\Catalog\Api\Data\ProductInterface::class, $entityData); + + $resultEntity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $resultEntity->setStoreId($store->getId()); + $resultEntity->load(1); + + $this->assertTrue($expected === $resultEntity->getData($code)); + } + + /** + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + * @covers \Magento\Eav\Model\ResourceModel\UpdateHandlerTest::execute + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @magentoDataFixture Magento/Catalog/_files/dropdown_attribute.php + * @magentoDataFixture Magento/Store/_files/second_store.php + * @dataProvider getCustomAttributeDataProvider + * @param $code + * @param $defaultStoreValue + * @param $snapshotValue + * @param $newValue + * @param $expected + */ + public function testExecuteProcessForCustomAttributeInCustomStore( + $code, + $defaultStoreValue, + $snapshotValue, + $newValue, + $expected + ) { + $store = Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class); + $store->load('fixture_second_store', 'code'); + + Bootstrap::getObjectManager() + ->create(\Magento\CatalogSearch\Model\Indexer\Fulltext\Processor::class) + ->reindexAll(); + + $attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class + ); + $attribute->loadByCode(4, $code); + + $options = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection::class + ); + $options->setAttributeFilter($attribute->getId()); + $optionIds = $options->getAllIds(); + + $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $entity->setStoreId(0); + $entity->load(1); + $entity->setData($code, $optionIds[$defaultStoreValue]); + $entity->save(); + + if ($snapshotValue !== '-') { + /** @var $options \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection */ + $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $entity->setStoreId($store->getId()); + $entity->load(1); + + if ($snapshotValue) { + $snapshotValue = $optionIds[$snapshotValue]; + } + + $entity->setData($code, $snapshotValue); + $entity->save(); + } + + $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $entity->setStoreId($store->getId()); + $entity->load(1); + + $updateHandler = Bootstrap::getObjectManager()->create(UpdateHandler::class); + + if ($newValue) { + $newValue = $optionIds[$newValue]; + } + + $entityData = array_merge($entity->getData(), [$code => $newValue]); + $updateHandler->execute(\Magento\Catalog\Api\Data\ProductInterface::class, $entityData); + + $resultEntity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); + $resultEntity->setStoreId($store->getId()); + $resultEntity->load(1); + + if ($expected !== null) { + $expected = $optionIds[$expected]; + } + + $this->assertTrue($expected === $resultEntity->getData($code)); + } + + /** + * @return array + */ + public function getAllStoresDataProvider() + { + return [ + ['description', '', 'not_empty_value', 'not_empty_value'], //0 + ['description', '', '', null], //1 + ['description', '', null, null], //2 + ['description', '', false, null], //3 + + ['description', 'not_empty_value', 'not_empty_value2', 'not_empty_value2'], //4 + ['description', 'not_empty_value', '', null], //5 + ['description', 'not_empty_value', null, null], //6 + ['description', 'not_empty_value', false, null], //7 + + ['description', null, 'not_empty_value', 'not_empty_value'], //8 + ['description', null, '', null], //9 + ['description', null, false, null], //10 + + ['description', false, 'not_empty_value', 'not_empty_value'], //11 + ['description', false, '', null], //12 + ['description', false, null, null], //13 + ]; + } + + /** + * @return array + */ + public function getCustomStoreDataProvider() + { + return [ + ['description', '', 'not_empty_value', 'not_empty_value'], //0 + ['description', '', '', null], //1 + ['description', '', null, 'Description with html tag'], //2 + ['description', '', false, 'Description with html tag'], //3 + + ['description', 'not_empty_value', 'not_empty_value2', 'not_empty_value2'], //4 + ['description', 'not_empty_value', '', null], //5 + ['description', 'not_empty_value', null, 'Description with html tag'], //6 + ['description', 'not_empty_value', false, 'Description with html tag'], //7 + + ['description', null, 'not_empty_value', 'not_empty_value'], //8 + ['description', null, '', null], //9 + ['description', null, false, 'Description with html tag'], //10 + + ['description', false, 'not_empty_value', 'not_empty_value'], //11 + ['description', false, '', null], //12 + ['description', false, null, 'Description with html tag'], //13 + ]; + } + + /** + * @return array + */ + public function getCustomAttributeDataProvider() + { + return [ + ['dropdown_attribute', 0, '', 1, 1], //0 + ['dropdown_attribute', 0, '', '', null], //1 + ['dropdown_attribute', 0, '', null, 0], //2 + ['dropdown_attribute', 0, '', false, 0], //3 + + ['dropdown_attribute', 0, 1, 2, 2], //4 + ['dropdown_attribute', 0, 1, '', null], //5 + ['dropdown_attribute', 0, 1, null, 0], //6 + ['dropdown_attribute', 0, 1, false, 0], //7 + + ['dropdown_attribute', 0, null, 1, 1], //8 + ['dropdown_attribute', 0, null, '', null], //9 + ['dropdown_attribute', 0, null, false, 0], //10 + + ['dropdown_attribute', 0, false, 1, 1], //11 + ['dropdown_attribute', 0, false, '', null], //12 + ['dropdown_attribute', 0, false, null, 0], //13 + + ['dropdown_attribute', 0, '-', 1, 1], //14 + ['dropdown_attribute', 0, '-', '', null], //15 + ['dropdown_attribute', 0, '-', null, 0], //16 + ['dropdown_attribute', 0, '-', false, 0], //17 + ]; + } } From ab2aa429ebc344b8c66e073ca54540889aa87845 Mon Sep 17 00:00:00 2001 From: Andrii Dimov Date: Thu, 27 Oct 2016 19:05:13 +0300 Subject: [PATCH 021/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - base integration tests for bundle price --- .../DynamicBundlePriceCalculatorTest.php | 243 ++++++++++++ .../FixedBundlePriceCalculatorTest.php | 355 ++++++++++++++++++ .../PriceCalculator/fixed_bundle_product.php | 2 +- .../fixed_bundle_product_rollback.php | 2 +- 4 files changed, 600 insertions(+), 2 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php new file mode 100644 index 0000000000000..8106e17d4c9b8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php @@ -0,0 +1,243 @@ + 'Some title', + 'required' => true, + 'type' => 'checkbox' + ]; + + protected $fixtureForProductOptionSelection = [ + 'sku' => null, // need to set this + 'option_id' => null, // need to set this + 'qty' => 1, + 'is_default' => true, + 'can_change_quantity' => 0 + ]; + + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + } + + /** + * @param $strategyModifiers array + * @param $expectedResults array + * @dataProvider getTestCases + * @magentoAppIsolation enabled + */ + public function testPriceForDynamicBundle(array $strategyModifiers, array $expectedResults) + { + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); + + foreach ($strategyModifiers as $modifier) { + if (method_exists($this, $modifier['modifierName'])) { + array_unshift($modifier['data'], $bundleProduct); + $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); + } + } + + $this->productRepository->save($bundleProduct); + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + + /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ + $priceInfo = $bundleProduct->getPriceInfo(); + $priceCode = \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE; + + $this->assertEquals( + $expectedResults['minimalPrice'], + $priceInfo->getPrice($priceCode)->getMinimalPrice()->getValue(), + 'Failed to check minimal price on product' + ); + + $this->assertEquals( + $expectedResults['maximalPrice'], + $priceInfo->getPrice($priceCode)->getMaximalPrice()->getValue(), + 'Failed to check maximal price on product' + ); + } + + public function getTestCases() + { + return [ + 'Testing price for dynamic bundle product with one simple' => [ + 'strategy' => $this->getProductWithOneSimple(), + 'expectedResults' => [ + // just price from simple1 + 'minimalPrice' => 10, + // just price from simple1 + 'maximalPrice' => 10 + ] + ], + 'Testing price for dynamic bundle product with three simples and differnt qty' => [ + 'strategy' => $this->getProductWithDifferentQty(), + 'expectedResults' => [ + // min price from simples 3*10 or 30 + 'minimalPrice' => 30, + // (3 * 10) + (2 * 20) + 30 + 'maximalPrice' => 100 + ] + ], + 'Testing price for dynamic bundle product with four simples and differnt price' => [ + 'strategy' => $this->getProductWithDifferentPrice(), + 'expectedResults' => [ + // 10 + 'minimalPrice' => 10, + // 10 + 20 + 30 + 'maximalPrice' => 60 + ] + ] + ]; + } + + public function getProductWithOneSimple() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 10, + ], + ] + ], + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithDifferentQty() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'qty' => 3, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 2, + ], + [ + 'sku' => 'simple3', + 'option_id' => 1, + 'qty' => 1, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithDifferentPrice() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'qty' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'qty' => 1, + ], + [ + 'sku' => 'simple3', + 'option_id' => 1, + 'qty' => 1, + ] + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + protected function getFixtureForProductOption(array $data = []) + { + $fixture = $this->fixtureForProductOption; + + // make title different for each call + $fixture['title'] .= ' ' . microtime(true); + + return array_merge($fixture, $data); + } + + protected function getFixtureForProductOptionSelection($data) + { + $fixture = $this->fixtureForProductOptionSelection; + + return array_merge($fixture, $data); + } + + protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + { + $options = []; + + foreach ($optionsData as $optionData) { + $links = []; + $linksData = $optionData['links']; + unset($optionData['links']); + + $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOption($optionData)]) + ->setSku($bundleProduct->getSku()) + ->setOptionid(null); + + foreach ($linksData as $linkData) { + $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); + } + + $option->setProductLinks($links); + $options[] = $option; + } + + $extension = $bundleProduct->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $bundleProduct->setExtensionAttributes($extension); + + return $bundleProduct; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php new file mode 100644 index 0000000000000..45b9031b3d26e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php @@ -0,0 +1,355 @@ + 'Some title', + 'required' => true, + 'type' => 'checkbox' + ]; + + protected $fixtureForProductOptionSelection = [ + 'sku' => null, // need to set this + 'option_id' => null, // need to set this + 'qty' => 1, + 'is_default' => true, + 'price' => null, // need to set this + 'price_type' => LinkInterface::PRICE_TYPE_FIXED, + 'can_change_quantity' => 0 + ]; + + protected $fixtureForProductCustomOption = [ + 'option_id' => null, + 'previous_group' => 'text', + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'sort_order' => 0, + 'price' => 100, + 'price_type' => 'fixed', + 'sku' => '1-text', + 'max_characters' => 100, + ]; + + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + } + + /** + * @param $strategyModifiers array + * @param $expectedResults array + * @dataProvider getTestCases + * @magentoAppIsolation enabled + */ + public function testPriceForFixedBundle(array $strategyModifiers, array $expectedResults) + { + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); + + foreach ($strategyModifiers as $modifier) { + if (method_exists($this, $modifier['modifierName'])) { + array_unshift($modifier['data'], $bundleProduct); + $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); + } + } + + $this->productRepository->save($bundleProduct); + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + + /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ + $priceInfo = $bundleProduct->getPriceInfo(); + $priceCode = \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE; + + $this->assertEquals( + $expectedResults['minimalPrice'], + $priceInfo->getPrice($priceCode)->getMinimalPrice()->getValue(), + 'Failed to check minimal price on product' + ); + + $this->assertEquals( + $expectedResults['maximalPrice'], + $priceInfo->getPrice($priceCode)->getMaximalPrice()->getValue(), + 'Failed to check maximal price on product' + ); + } + + + public function getTestCases() + { + return [ + 'Testing price for fixed bundle product with one simple' => [ + 'strategy' => $this->getProductWithOneSimple(), + 'expectedResults' => [ + // 110 + 10 (price from simple1) + 'minimalPrice' => 120, + // 110 + 10 (sum of simple price) + 'maximalPrice' => 120 + ] + ], + 'Testing price for fixed bundle product with three simples and differnt qty' => [ + 'strategy' => $this->getProductWithDifferentQty(), + 'expectedResults' => [ + // 110 + 10 (min price from simples) + 'minimalPrice' => 120, + // 110 + (3 * 10) + (2 * 10) + 10 + 'maximalPrice' => 170 + ] + ], + 'Testing price for fixed bundle product with three simples and differnt price' => [ + 'strategy' => $this->getProductWithDifferentPrice(), + 'expectedResults' => [ + // 110 + 10 + 'minimalPrice' => 120, + // 110 + 60 + 'maximalPrice' => 170 + ] + ], + 'Testing price for fixed bundle product with three simples' => [ + 'strategy' => $this->getProductWithSamePrice(), + 'expectedResults' => [ + // 110 + 10 + 'minimalPrice' => 120, + // 110 + 30 + 'maximalPrice' => 140 + ] + ] + ]; + } + + public function getProductWithOneSimple() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 10, + ], + ] + ], + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithDifferentQty() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 10, + 'qty' => 3, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 10, + 'qty' => 2, + ], + [ + 'sku' => 'simple3', + 'option_id' => 1, + 'price' => 10, + 'qty' => 1, + ], + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithSamePrice() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 10, + 'qty' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 10, + 'qty' => 1, + ], + [ + 'sku' => 'simple3', + 'option_id' => 1, + 'price' => 10, + 'qty' => 1, + ] + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + public function getProductWithDifferentPrice() + { + $optionsData = [ + [ + 'links' => [ + [ + 'sku' => 'simple1', + 'option_id' => 1, + 'price' => 10, + 'qty' => 1, + ], + [ + 'sku' => 'simple2', + 'option_id' => 1, + 'price' => 20, + 'qty' => 1, + ], + [ + 'sku' => 'simple3', + 'option_id' => 1, + 'price' => 30, + 'qty' => 1, + ] + ] + ] + ]; + + return [ + [ + 'modifierName' => 'addSimpleProduct', + 'data' => [$optionsData] + ], + ]; + } + + protected function getFixtureForProductOption(array $data = []) + { + $fixture = $this->fixtureForProductOption; + + // make title different for each call + $fixture['title'] .= ' ' . microtime(true); + + return array_merge($fixture, $data); + } + + protected function getFixtureForProductOptionSelection($data) + { + $fixture = $this->fixtureForProductOptionSelection; + + return array_merge($fixture, $data); + } + + protected function getFixtureForProductCustomOption(array $data = []) + { + $fixture = $this->fixtureForProductCustomOption; + + // make title and sku different for each call + $fixture['title'] .= ' ' . microtime(true); + $fixture['sku'] .= ' ' . microtime(true); + + return array_merge($fixture, $data); + } + + protected function addSpecialPrice(\Magento\Catalog\Model\Product $bundleProduct, $discount) + { + $bundleProduct->setSpecialPrice($discount); + + return $bundleProduct; + } + + protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + { + $options = []; + + foreach ($optionsData as $optionData) { + $links = []; + $linksData = $optionData['links']; + unset($optionData['links']); + + $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOption($optionData)]) + ->setSku($bundleProduct->getSku()) + ->setOptionid(null); + + foreach ($linksData as $linkData) { + $linkData['option_id'] = $option->getId(); // ??? looks like needed + $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); + } + + $option->setProductLinks($links); + $options[] = $option; + } + + $extension = $bundleProduct->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $bundleProduct->setExtensionAttributes($extension); + + return $bundleProduct; + } + + protected function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + { + /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */ + $customOptionFactory = $this->objectManager + ->create(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); + + $options = []; + foreach ($optionsData as $optionData) { + $customOption = $customOptionFactory->create( + [ + 'data' => $this->getFixtureForProductCustomOption($optionData) + ] + ); + $customOption->setProductSku($bundleProduct->getSku()); + $customOption->setOptionId(null); + + $options[] = $customOption; + } + + $bundleProduct->setOptions($options); + $bundleProduct->setCanSaveCustomOptions(true); + + return $bundleProduct; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product.php index f77d7dc8bd5bc..7b501db8e89a4 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -require __DIR__ . '/../../../../Magento/Catalog/_files/multiple_products.php'; +require __DIR__ . '/../../../../Magento/Bundle/_files/multiple_products.php'; $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); $productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php index 4f42bba96c177..bb41cddb8e0a4 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -require __DIR__ . '/../../../../Magento/Catalog/_files/multiple_products_rollback.php'; +require __DIR__ . '/../../../../Magento/Bundle/_files/multiple_products_rollback.php'; /** @var \Magento\Framework\Registry $registry */ $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); From 611838d5680371e3249d97fa3411b3d6ae699ec5 Mon Sep 17 00:00:00 2001 From: Michail Slabko Date: Thu, 27 Oct 2016 19:22:53 +0300 Subject: [PATCH 022/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-60106: Bundle from-to price calculation is wrong --- .../ResourceModel/Selection/Collection.php | 10 ++++++++++ .../Bundle/Pricing/Adjustment/Calculator.php | 17 +++++++++++++++-- .../PriceCalculator/dynamic_bundle_product.php | 2 +- .../dynamic_bundle_product_rollback.php | 2 +- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php index 4aff7c14c7efa..83a2664ec70f3 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php @@ -279,4 +279,14 @@ public function addPriceFilter($product, $searchMin, $useRegularPrice = false) $this->getSelect()->limit(1); return $this; } + + /** + * Clear collection data after clone + */ + public function __clone() + { + parent::__clone(); + $this->removeAttributeToSelect(); + $this->clear(); + } } diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php index b64494ab40000..2048b3eaaa8ba 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php @@ -216,9 +216,9 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR $selectionsCollection->addAttributeToSelect('special_price_from'); $selectionsCollection->addAttributeToSelect('special_price_to'); $selectionsCollection->addAttributeToSelect('tax_class_id'); - $selectionsCollection->addTierPriceData(); } - $selection = $selectionsCollection->fetchItem(); + + $selection = $selectionsCollection->getFirstItem(); $priceList[] = $this->selectionFactory->create( $bundleProduct, $selection, @@ -230,6 +230,19 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR } } + + if ($searchMin && $bundleProduct->getPriceType() == Price::PRICE_TYPE_DYNAMIC && !$productHasRequiredOption) { + $minPrice = null; + $priceSelection = null; + foreach ($priceList as $price) { + $minPriceTmp = $price->getAmount()->getValue() * $price->getQuantity(); + if (!$minPrice || $minPriceTmp < $minPrice) { + $priceSelection = $price; + } + } + $priceList = [$priceSelection]; + } + return $priceList; } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php index 726b8a36fb301..218ae90d4509f 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -require __DIR__ . '/../../../../Magento/Catalog/_files/multiple_products.php'; +require __DIR__ . '/../../../../Magento/Bundle/_files/multiple_products.php'; $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); $productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php index 4f42bba96c177..bb41cddb8e0a4 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -require __DIR__ . '/../../../../Magento/Catalog/_files/multiple_products_rollback.php'; +require __DIR__ . '/../../../../Magento/Bundle/_files/multiple_products_rollback.php'; /** @var \Magento\Framework\Registry $registry */ $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); From 57a5fb57670f2d3d2fbd6b4d25e4028143bdeb73 Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Thu, 27 Oct 2016 19:30:13 +0300 Subject: [PATCH 023/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - updates for isSaleable test --- .../Bundle/Model/Product/IsSaleableTest.php | 81 +++++-------------- 1 file changed, 18 insertions(+), 63 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php index 20d0fb2e21f1f..aa222e4f9f1a4 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php @@ -8,6 +8,8 @@ /** * Test class for \Magento\Bundle\Model\Product\Type (bundle product type) + * + * @magentoDataFixtureBeforeTransaction Magento/Bundle/_files/issaleable_product.php */ class IsSaleableTest extends \PHPUnit_Framework_TestCase { @@ -30,13 +32,11 @@ protected function setUp() /** * check bundle product is saleable if his status is enabled * - * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable */ public function testIsSaleableOnEnabledStatus() { - $bundleProduct = $this->productRepository->get('bundle-product'); $bundleProduct->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED); @@ -49,7 +49,6 @@ public function testIsSaleableOnEnabledStatus() /** * check bundle product is NOT saleable if his status is disabled * - * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable */ @@ -68,7 +67,6 @@ public function testIsSaleableOnDisabledStatus() * check bundle product is saleable if his status is enabled * and it has internal data is_salable = true * - * @magentoDataFixtureBeforeTransaction Magento/Bundle/_files/issaleable_product.php * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable */ @@ -88,7 +86,6 @@ public function testIsSaleableOnEnabledStatusAndIsSalableIsTrue() * check bundle product is NOT saleable if * his status is enabled but his data is_salable = false * - * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable */ @@ -107,7 +104,6 @@ public function testIsSaleableOnEnabledStatusAndIsSalableIsFalse() /** * check bundle product is saleable if it has all_items_salable = true * - * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable */ @@ -125,7 +121,6 @@ public function testIsSaleableOnAllItemsSalableIsTrue() /** * check bundle product is NOT saleable if it has all_items_salable = false * - * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable */ @@ -143,14 +138,12 @@ public function testIsSaleableOnAllItemsSalableIsFalse() /** * check bundle product is NOT saleable if it has no options * - * @magentoDataFixtureBeforeTransaction Magento/Bundle/_files/issaleable_product.php * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable */ public function testIsSaleableOnBundleWithoutOptions() { $optionRepository = $this->objectManager->create(\Magento\Bundle\Api\ProductOptionRepositoryInterface::class); - $bundleProduct = $this->productRepository->get('bundle-product'); // TODO: make cleaner option deletion after fix MAGETWO-59465 @@ -160,8 +153,8 @@ public function testIsSaleableOnBundleWithoutOptions() } $ea->setBundleProductOptions([]); $bundleProduct->setExtensionAttributes($ea); - $bundleProduct->setBundleOptionsData([]); - $this->productRepository->save($bundleProduct); + + $bundleProduct = $this->productRepository->save($bundleProduct); $this->assertFalse( $bundleProduct->isSalable(), @@ -172,7 +165,6 @@ public function testIsSaleableOnBundleWithoutOptions() /** * check bundle product is NOT saleable if it has no selections * - * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable */ @@ -194,8 +186,6 @@ public function testIsSaleableOnBundleWithoutSelections() $linkManager->removeChild($bundleProductSku, $link->getOptionId(), $link->getSku()); } - $bundleProduct = $this->productRepository->get($bundleProductSku, true, null, true); - $this->assertFalse( $bundleProduct->isSalable(), 'Bundle product supposed to be non saleable if it has no selections' @@ -206,7 +196,6 @@ public function testIsSaleableOnBundleWithoutSelections() * check bundle product is NOT saleable if * all his selections are not saleable * - * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable */ @@ -231,7 +220,6 @@ public function testIsSaleableOnBundleWithoutSaleableSelections() * check bundle product is NOT saleable if * it has at least one required option without saleable selections * - * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable */ @@ -256,7 +244,6 @@ public function testIsSaleableOnBundleWithoutSaleableSelectionsOnRequiredOption( * check bundle product is NOT saleable if * there are not enough qty of selection on required option * - * @magentoDataFixtureBeforeTransaction Magento/Bundle/_files/issaleable_product.php * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable */ @@ -272,65 +259,33 @@ public function testIsSaleableOnBundleWithNotEnoughQtyOfSelection() ); } - /** - * check bundle product is saleable if - * all his selections has not selection qty - * - * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php - * @magentoAppIsolation enabled - * @covers \Magento\Bundle\Model\Product\Type::isSalable - */ - public function testIsSaleableOnBundleWithoutSelectionQty() - { - $this->setQtyForSelections(['simple1', 'simple2', 'simple3', 'simple4', 'simple5'], 1); - - $bundleProduct = $this->productRepository->get('bundle-product', false, null, true); - $bundleType = $bundleProduct->getTypeInstance(); - - /** @var \Magento\Bundle\Model\Product\Type $bundleType */ - $options = $bundleType->getOptionsCollection($bundleProduct); - $selections = $bundleType->getSelectionsCollection($options->getAllIds(), $bundleProduct); - - foreach ($selections as $link) { - $link->setSelectionQty(null); - } - - $bundleProduct->setBundleOptionsData([]); - $bundleProduct->setBundleSelectionsData([]); - $this->productRepository->save($bundleProduct); - - $this->assertTrue( - $bundleProduct->isSalable(), - 'Bundle product supposed to be saleable if all his selections has no selection qty' - ); - } - /** * check bundle product is saleable if * all his selections have selection_can_change_qty = 1 * - * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable */ public function testIsSaleableOnBundleWithSelectionCanChangeQty() { $this->setQtyForSelections(['simple1', 'simple2', 'simple3', 'simple4', 'simple5'], 1); + $bundleProduct = $this->productRepository->get('bundle-product'); + $options = $bundleProduct->getExtensionAttributes()->getBundleProductOptions(); - $bundleProduct = $this->productRepository->get('bundle-product', false, null, true); - $bundleType = $bundleProduct->getTypeInstance(); + foreach ($options as $productOption) { + $links = $productOption->getProductLinks(); + foreach ($links as $link) { + $link->setSelectionCanChangeQuantity(1); + } - /** @var \Magento\Bundle\Model\Product\Type $bundleType */ - $options = $bundleType->getOptionsCollection($bundleProduct); - $selections = $bundleType->getSelectionsCollection($options->getAllIds(), $bundleProduct); - - foreach ($selections as $link) { - $link->setSelectionCanChangeQty(1); + $productOption->setProductLinks($links); } - $bundleProduct->setBundleOptionsData([]); - $bundleProduct->setBundleSelectionsData([]); - $this->productRepository->save($bundleProduct); + $extension = $bundleProduct->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $bundleProduct->setExtensionAttributes($extension); + + $bundleProduct = $this->productRepository->save($bundleProduct); $this->assertTrue( $bundleProduct->isSalable(), @@ -341,7 +296,7 @@ public function testIsSaleableOnBundleWithSelectionCanChangeQty() private function setQtyForSelections($productsSku, $qty) { foreach ($productsSku as $productSku) { - $product = $this->productRepository->get($productSku, false, null, true); + $product = $this->productRepository->get($productSku); $ea = $product->getExtensionAttributes(); $ea->getStockItem()->setQty($qty); $this->productRepository->save($product); From b024f0592f0d8f4a43b1be7d1d51a38d04e97846 Mon Sep 17 00:00:00 2001 From: Vitaliy Goncharenko Date: Thu, 27 Oct 2016 19:35:30 +0300 Subject: [PATCH 024/161] MAGETWO-53583: "Use Default" checkbox is checked again after saving empty fields (description, name, etc) - fixed static --- .../Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php b/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php index 8851ab0c71eb9..cd110713711e0 100644 --- a/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php +++ b/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php @@ -9,7 +9,8 @@ use Magento\TestFramework\Helper\Bootstrap; /** - * Update handler test. + * @magentoAppArea adminhtml + * @magentoAppIsolation enabled */ class UpdateHandlerTest extends \PHPUnit_Framework_TestCase { From 3be660c3f48ed8189afc72d4f94e2e23e6ee51c6 Mon Sep 17 00:00:00 2001 From: Michail Slabko Date: Thu, 27 Oct 2016 22:11:50 +0300 Subject: [PATCH 025/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-60106: Bundle from-to price calculation is wrong --- ...icBundleWithSpecialPriceCalculatorTest.php | 30 ------------------- ...dle_product_with_catalog_rule_rollback.php | 2 +- 2 files changed, 1 insertion(+), 31 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php index 9762df3a5ddaf..e0d5273501103 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php @@ -78,15 +78,6 @@ public function testPriceForDynamicBundle(array $strategyModifiers, array $expec public function getTestCases() { return [ - 'Testing price for dynamic bundle product with sub items and without any discounts' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy(), - 'expectedResults' => [ - // just price from simple1 - 'minimalPrice' => 10, - // just price from simple1 - 'maximalPrice' => 10 - ] - ], 'Testing price for dynamic bundle product with special price and sub items Configuration #1' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1(), 'expectedResults' => [ @@ -180,27 +171,6 @@ public function getTestCases() ]; } - public function getProductWithSubItemsAndOptionsStrategy() - { - $optionsData = [ - [ - 'links' => [ - [ - 'sku' => 'simple1', - 'option_id' => 1, - ], - ] - ], - ]; - - return [ - [ - 'modifierName' => 'addSimpleProduct', - 'data' => [$optionsData] - ], - ]; - } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1() { $optionsData = [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule_rollback.php index 51d234e56ab8b..50cb07079c24f 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule_rollback.php @@ -4,4 +4,4 @@ * See COPYING.txt for license details. */ -require __DIR__ . '/dynamic_bundle_product.php'; +require __DIR__ . '/dynamic_bundle_product_rollback.php'; From 8f1f08740e744a9194da1b31b6d835c98addc639 Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Fri, 28 Oct 2016 10:19:18 +0300 Subject: [PATCH 026/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - some fixes for isSaleable --- app/code/Magento/Bundle/Model/Product/Type.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Bundle/Model/Product/Type.php b/app/code/Magento/Bundle/Model/Product/Type.php index a31a129ff5972..d62613c221528 100644 --- a/app/code/Magento/Bundle/Model/Product/Type.php +++ b/app/code/Magento/Bundle/Model/Product/Type.php @@ -554,18 +554,17 @@ public function isSalable($product) return $product->getData('all_items_salable'); } - $optionCollection = $this->getOptionsCollection($product); - - if (!count($optionCollection->getItems())) { + if (!$this->getOptionsCollection($product)->getSize()) { return false; } $isSalable = true; - foreach ($optionCollection->getItems() as $option) { + foreach ($this->getOptionsCollection($product)->getItems() as $option) { if ($option->getRequired()) { $hasSalable = false; $selectionsCollection = $this->_bundleCollection->create(); + $selectionsCollection->addAttributeToSelect('status'); $selectionsCollection->addQuantityFilter(); $selectionsCollection->addFilterByRequiredOptions(); $selectionsCollection->setOptionIdsFilter([$option->getId()]); From 8fe89bdeb51fcee5125803ed9e7a271d1ab17da4 Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Fri, 28 Oct 2016 13:37:13 +0300 Subject: [PATCH 027/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - updates for isSaleable test --- .../Bundle/Model/Product/IsSaleableTest.php | 83 +++++++++++++++++-- 1 file changed, 78 insertions(+), 5 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php index aa222e4f9f1a4..b1fe33e843b65 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php @@ -9,7 +9,7 @@ /** * Test class for \Magento\Bundle\Model\Product\Type (bundle product type) * - * @magentoDataFixtureBeforeTransaction Magento/Bundle/_files/issaleable_product.php + * @magentoDataFixture Magento/Bundle/_files/issaleable_product.php */ class IsSaleableTest extends \PHPUnit_Framework_TestCase { @@ -170,9 +170,7 @@ public function testIsSaleableOnBundleWithoutOptions() */ public function testIsSaleableOnBundleWithoutSelections() { - $bundleProductSku = 'bundle-product'; - - $bundleProduct = $this->productRepository->get($bundleProductSku, true, null, true); + $bundleProduct = $this->productRepository->get('bundle-product', true, null, true); $bundleType = $bundleProduct->getTypeInstance(); /** @var \Magento\Bundle\Model\LinkManagement $linkManager */ $linkManager = $this->objectManager->create(\Magento\Bundle\Model\LinkManagement::class); @@ -183,9 +181,10 @@ public function testIsSaleableOnBundleWithoutSelections() foreach ($selections as $link) { /** @var \Magento\Bundle\Model\Selection $link */ - $linkManager->removeChild($bundleProductSku, $link->getOptionId(), $link->getSku()); + $linkManager->removeChild('bundle-product', $link->getOptionId(), $link->getSku()); } + $bundleProduct = $this->productRepository->get('bundle-product', false, null, true); $this->assertFalse( $bundleProduct->isSalable(), 'Bundle product supposed to be non saleable if it has no selections' @@ -293,6 +292,80 @@ public function testIsSaleableOnBundleWithSelectionCanChangeQty() ); } + /** + * check bundle product is not saleable if + * all his options are not required and selections are not saleable + * + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnBundleWithoutRequiredOptions() + { + // making selections as not saleable + $productsSku = ['simple1', 'simple2', 'simple3', 'simple4', 'simple5']; + foreach ($productsSku as $productSku) { + $product = $this->productRepository->get($productSku); + $product->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED); + $this->productRepository->save($product); + } + + $bundleProduct = $this->productRepository->get('bundle-product'); + + // setting all options as not required + $options = $bundleProduct->getExtensionAttributes()->getBundleProductOptions(); + foreach ($options as $productOption) { + $productOption->setRequired(false); + } + + $extension = $bundleProduct->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $bundleProduct->setExtensionAttributes($extension); + $bundleProduct = $this->productRepository->save($bundleProduct); + + $this->assertFalse( + $bundleProduct->isSalable(), + 'Bundle product supposed to be not saleable if all his options are not required and selections are not saleable' + ); + } + + /** + * check bundle product is saleable if + * it has at least one not required option with saleable selections + * + * @magentoAppIsolation enabled + * @covers \Magento\Bundle\Model\Product\Type::isSalable + */ + public function testIsSaleableOnBundleWithOneSaleableSelection() + { + // making selections as not saleable except simple1 + $productsSku = ['simple2', 'simple3', 'simple4', 'simple5']; + + foreach ($productsSku as $productSku) { + $product = $this->productRepository->get($productSku); + $product->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED); + $this->productRepository->save($product); + } + + $bundleProduct = $this->productRepository->get('bundle-product'); + + // setting all options as not required + $options = $bundleProduct->getExtensionAttributes()->getBundleProductOptions(); + foreach ($options as $productOption) { + $productOption->setRequired(false); + } + + $extension = $bundleProduct->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $bundleProduct->setExtensionAttributes($extension); + + $bundleProduct = $this->productRepository->save($bundleProduct); + + $this->assertTrue( + $bundleProduct->isSalable(), + 'Bundle product supposed to be saleable if it has at least one not required option with saleable selection' + ); + } + private function setQtyForSelections($productsSku, $qty) { foreach ($productsSku as $productSku) { From b4a4e110be6a1dce5bd2dc136b8254b7903d45e3 Mon Sep 17 00:00:00 2001 From: Vitaliy Goncharenko Date: Fri, 28 Oct 2016 13:45:12 +0300 Subject: [PATCH 028/161] MAGETWO-53583: "Use Default" checkbox is checked again after saving empty fields (description, name, etc) - fixed integration save category test --- .../Magento/Catalog/Controller/Adminhtml/CategoryTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/CategoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/CategoryTest.php index f84c661126b04..5db10afdee002 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/CategoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/CategoryTest.php @@ -233,7 +233,7 @@ public function saveActionDataProvider() 'display_mode' => true, 'meta_title' => true, 'custom_design' => true, - 'page_layout' => false, + 'page_layout' => true, 'is_active' => true, 'include_in_menu' => true, 'landing_page' => true, @@ -242,7 +242,7 @@ public function saveActionDataProvider() 'description' => true, 'meta_keywords' => true, 'meta_description' => true, - 'custom_layout_update' => false, + 'custom_layout_update' => true, 'custom_design_from' => true, 'custom_design_to' => true, 'filter_price_range' => false From c010dc6499ef1287a1a7c057f1ec2f2b278069e1 Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Fri, 28 Oct 2016 14:41:30 +0300 Subject: [PATCH 029/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - fixes for checking that bundle is saleable --- .../Magento/Bundle/Model/Product/Type.php | 42 +++++++++---------- .../Bundle/Model/Product/IsSaleableTest.php | 4 +- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/app/code/Magento/Bundle/Model/Product/Type.php b/app/code/Magento/Bundle/Model/Product/Type.php index d62613c221528..31789442ce63b 100644 --- a/app/code/Magento/Bundle/Model/Product/Type.php +++ b/app/code/Magento/Bundle/Model/Product/Type.php @@ -554,33 +554,31 @@ public function isSalable($product) return $product->getData('all_items_salable'); } - if (!$this->getOptionsCollection($product)->getSize()) { - return false; - } - - $isSalable = true; + $isSalable = false; foreach ($this->getOptionsCollection($product)->getItems() as $option) { - if ($option->getRequired()) { - $hasSalable = false; - - $selectionsCollection = $this->_bundleCollection->create(); - $selectionsCollection->addAttributeToSelect('status'); - $selectionsCollection->addQuantityFilter(); - $selectionsCollection->addFilterByRequiredOptions(); - $selectionsCollection->setOptionIdsFilter([$option->getId()]); - - foreach ($selectionsCollection as $selection) { - if ($selection->isSalable()) { - $hasSalable = true; - break; - } - } + $hasSalable = false; + + $selectionsCollection = $this->_bundleCollection->create(); + $selectionsCollection->addAttributeToSelect('status'); + $selectionsCollection->addQuantityFilter(); + $selectionsCollection->addFilterByRequiredOptions(); + $selectionsCollection->setOptionIdsFilter([$option->getId()]); - if (!$hasSalable) { - $isSalable = false; + foreach ($selectionsCollection as $selection) { + if ($selection->isSalable()) { + $hasSalable = true; break; } } + + if ($hasSalable) { + $isSalable = true; + } + + if (!$hasSalable && $option->getRequired()) { + $isSalable = false; + break; + } } $product->setData('all_items_salable', $isSalable); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php index b1fe33e843b65..fb04b268bfdfe 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php @@ -337,8 +337,8 @@ public function testIsSaleableOnBundleWithoutRequiredOptions() */ public function testIsSaleableOnBundleWithOneSaleableSelection() { - // making selections as not saleable except simple1 - $productsSku = ['simple2', 'simple3', 'simple4', 'simple5']; + // making selections as not saleable except simple3 + $productsSku = ['simple1', 'simple2', 'simple4', 'simple5']; foreach ($productsSku as $productSku) { $product = $this->productRepository->get($productSku); From 0cbd3255de8d7eff980d9d4ef0db72a03693bdbe Mon Sep 17 00:00:00 2001 From: Michail Slabko Date: Fri, 28 Oct 2016 15:50:13 +0300 Subject: [PATCH 030/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-60106: Bundle from-to price calculation is wrong --- .../Bundle/Pricing/Adjustment/Calculator.php | 12 +- .../Bundle/Model/Product/BundlePrice.php | 140 ++++++++++++++ .../DynamicBundlePriceCalculatorTest.php | 106 ++--------- .../FixedBundlePriceCalculatorTest.php | 175 +++--------------- 4 files changed, 181 insertions(+), 252 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePrice.php diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php index 2048b3eaaa8ba..3a83a38ba6510 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php @@ -180,8 +180,14 @@ public function getAmountWithoutOption($amount, Product $saleableItem) protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useRegularPrice = false) { // Flag shows - is it necessary to find minimal option amount in case if all options are not required - $productHasRequiredOption = $this->hasRequiredOption($bundleProduct); - $canSkipRequiredOptions = $searchMin && $productHasRequiredOption; + $shouldFindMinOption = false; + if ($searchMin + && $bundleProduct->getPriceType() == Price::PRICE_TYPE_DYNAMIC + && !$this->hasRequiredOption($bundleProduct) + ) { + $shouldFindMinOption = true; + } + $canSkipRequiredOptions = $searchMin && !$shouldFindMinOption; $priceList = []; foreach ($this->getBundleOptions($bundleProduct) as $option) { @@ -231,7 +237,7 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR } - if ($searchMin && $bundleProduct->getPriceType() == Price::PRICE_TYPE_DYNAMIC && !$productHasRequiredOption) { + if ($shouldFindMinOption) { $minPrice = null; $priceSelection = null; foreach ($priceList as $price) { diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePrice.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePrice.php new file mode 100644 index 0000000000000..f226b514c2304 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePrice.php @@ -0,0 +1,140 @@ +objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + } + + /** + * Get test cases + * @return array + */ + abstract public function getTestCases(); + + /** + * @param array $strategyModifiers + * @return \Magento\Catalog\Api\Data\ProductInterface + */ + protected function prepareFixture($strategyModifiers) + { + $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); + + foreach ($strategyModifiers as $modifier) { + if (method_exists($this, $modifier['modifierName'])) { + array_unshift($modifier['data'], $bundleProduct); + $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); + } + } + + $this->productRepository->save($bundleProduct); + return $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + } + + /** + * Add simple product to bundle + * + * @param \Magento\Catalog\Model\Product $bundleProduct + * @param array $optionsData + * @return \Magento\Catalog\Model\Product + */ + protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + { + $options = []; + + foreach ($optionsData as $optionData) { + $links = []; + $linksData = $optionData['links']; + unset($optionData['links']); + + $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) + ->create(['data' => $this->getFixtureForProductOption($optionData)]) + ->setSku($bundleProduct->getSku()); + + foreach ($linksData as $linkData) { + $linkData['option_id'] = $option->getId(); + $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) + ->create(['data' => $linkData]); + } + + $option->setProductLinks($links); + $options[] = $option; + } + + $extension = $bundleProduct->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $bundleProduct->setExtensionAttributes($extension); + + return $bundleProduct; + } + + /** + * @param array $fixture + * @return array + */ + private function getFixtureForProductCustomOption(array $fixture = []) + { + $fixture['title'] = 'Custom Option Title ' . microtime(true); + $fixture['sku'] = 'custom_option_sku_' . microtime(true); + + return $fixture; + } + + /** + * @param \Magento\Catalog\Model\Product $bundleProduct + * @param array $optionsData + * @return \Magento\Catalog\Model\Product + */ + protected function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + { + /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */ + $customOptionFactory = $this->objectManager + ->create(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); + + $options = []; + foreach ($optionsData as $optionData) { + $customOption = $customOptionFactory->create( + [ + 'data' => $this->getFixtureForProductCustomOption($optionData) + ] + ); + $customOption->setProductSku($bundleProduct->getSku()); + $customOption->setOptionId(null); + + $options[] = $customOption; + } + + $bundleProduct->setOptions($options); + $bundleProduct->setCanSaveCustomOptions(true); + + return $bundleProduct; + } + + /** + * @param array $fixture + * @return array + */ + private function getFixtureForProductOption(array $fixture = []) + { + $fixture['title'] = 'Option title' . microtime(true); + + return $fixture; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php index 8106e17d4c9b8..fbb785b43a6e0 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php @@ -10,53 +10,17 @@ * @magentoDataFixture Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php * @magentoAppArea frontend */ -class DynamicBundlePriceCalculatorTest extends \PHPUnit_Framework_TestCase +class DynamicBundlePriceCalculatorTest extends BundlePrice { - /** @var \Magento\TestFramework\Helper\Bootstrap */ - protected $objectManager; - - /** @var \Magento\Catalog\Api\ProductRepositoryInterface */ - protected $productRepository; - - protected $fixtureForProductOption = [ - 'title' => 'Some title', - 'required' => true, - 'type' => 'checkbox' - ]; - - protected $fixtureForProductOptionSelection = [ - 'sku' => null, // need to set this - 'option_id' => null, // need to set this - 'qty' => 1, - 'is_default' => true, - 'can_change_quantity' => 0 - ]; - - protected function setUp() - { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); - } - /** - * @param $strategyModifiers array - * @param $expectedResults array + * @param array $strategyModifiers + * @param array $expectedResults * @dataProvider getTestCases * @magentoAppIsolation enabled */ public function testPriceForDynamicBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); - - foreach ($strategyModifiers as $modifier) { - if (method_exists($this, $modifier['modifierName'])) { - array_unshift($modifier['data'], $bundleProduct); - $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); - } - } - - $this->productRepository->save($bundleProduct); - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + $bundleProduct = $this->prepareFixture($strategyModifiers); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -112,11 +76,12 @@ public function getProductWithOneSimple() { $optionsData = [ [ + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, - 'price' => 10, + 'qty' => 1, ], ] ], @@ -134,20 +99,19 @@ public function getProductWithDifferentQty() { $optionsData = [ [ + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, 'qty' => 3, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 2, ], [ 'sku' => 'simple3', - 'option_id' => 1, 'qty' => 1, ], ] @@ -166,20 +130,19 @@ public function getProductWithDifferentPrice() { $optionsData = [ [ + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 1, ], [ 'sku' => 'simple3', - 'option_id' => 1, 'qty' => 1, ] ] @@ -193,51 +156,4 @@ public function getProductWithDifferentPrice() ], ]; } - - protected function getFixtureForProductOption(array $data = []) - { - $fixture = $this->fixtureForProductOption; - - // make title different for each call - $fixture['title'] .= ' ' . microtime(true); - - return array_merge($fixture, $data); - } - - protected function getFixtureForProductOptionSelection($data) - { - $fixture = $this->fixtureForProductOptionSelection; - - return array_merge($fixture, $data); - } - - protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) - { - $options = []; - - foreach ($optionsData as $optionData) { - $links = []; - $linksData = $optionData['links']; - unset($optionData['links']); - - $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOption($optionData)]) - ->setSku($bundleProduct->getSku()) - ->setOptionid(null); - - foreach ($linksData as $linkData) { - $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); - } - - $option->setProductLinks($links); - $options[] = $option; - } - - $extension = $bundleProduct->getExtensionAttributes(); - $extension->setBundleProductOptions($options); - $bundleProduct->setExtensionAttributes($extension); - - return $bundleProduct; - } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php index 45b9031b3d26e..66ae6a975a72c 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php @@ -12,49 +12,8 @@ * @magentoDataFixture Magento/Bundle/_files/PriceCalculator/fixed_bundle_product.php * @magentoAppArea frontend */ -class FixedBundlePriceCalculatorTest extends \PHPUnit_Framework_TestCase +class FixedBundlePriceCalculatorTest extends BundlePrice { - /** @var \Magento\TestFramework\Helper\Bootstrap */ - protected $objectManager; - - /** @var \Magento\Catalog\Api\ProductRepositoryInterface */ - protected $productRepository; - - protected $fixtureForProductOption = [ - 'title' => 'Some title', - 'required' => true, - 'type' => 'checkbox' - ]; - - protected $fixtureForProductOptionSelection = [ - 'sku' => null, // need to set this - 'option_id' => null, // need to set this - 'qty' => 1, - 'is_default' => true, - 'price' => null, // need to set this - 'price_type' => LinkInterface::PRICE_TYPE_FIXED, - 'can_change_quantity' => 0 - ]; - - protected $fixtureForProductCustomOption = [ - 'option_id' => null, - 'previous_group' => 'text', - 'title' => 'Test Field', - 'type' => 'field', - 'is_require' => 1, - 'sort_order' => 0, - 'price' => 100, - 'price_type' => 'fixed', - 'sku' => '1-text', - 'max_characters' => 100, - ]; - - protected function setUp() - { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); - } - /** * @param $strategyModifiers array * @param $expectedResults array @@ -63,17 +22,7 @@ protected function setUp() */ public function testPriceForFixedBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); - - foreach ($strategyModifiers as $modifier) { - if (method_exists($this, $modifier['modifierName'])) { - array_unshift($modifier['data'], $bundleProduct); - $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); - } - } - - $this->productRepository->save($bundleProduct); - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + $bundleProduct = $this->prepareFixture($strategyModifiers); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -139,11 +88,14 @@ public function getProductWithOneSimple() { $optionsData = [ [ + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, 'price' => 10, + 'qty' => 1, + 'price_type' => LinkInterface::PRICE_TYPE_FIXED, ], ] ], @@ -161,24 +113,26 @@ public function getProductWithDifferentQty() { $optionsData = [ [ + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, 'price' => 10, 'qty' => 3, + 'price_type' => LinkInterface::PRICE_TYPE_FIXED, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 10, 'qty' => 2, + 'price_type' => LinkInterface::PRICE_TYPE_FIXED, ], [ 'sku' => 'simple3', - 'option_id' => 1, 'price' => 10, 'qty' => 1, + 'price_type' => LinkInterface::PRICE_TYPE_FIXED, ], ] ] @@ -196,24 +150,26 @@ public function getProductWithSamePrice() { $optionsData = [ [ + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, 'price' => 10, 'qty' => 1, + 'price_type' => LinkInterface::PRICE_TYPE_FIXED, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 10, 'qty' => 1, + 'price_type' => LinkInterface::PRICE_TYPE_FIXED, ], [ 'sku' => 'simple3', - 'option_id' => 1, 'price' => 10, 'qty' => 1, + 'price_type' => LinkInterface::PRICE_TYPE_FIXED, ] ] ] @@ -231,24 +187,26 @@ public function getProductWithDifferentPrice() { $optionsData = [ [ + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, 'price' => 10, 'qty' => 1, + 'price_type' => LinkInterface::PRICE_TYPE_FIXED, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 20, 'qty' => 1, + 'price_type' => LinkInterface::PRICE_TYPE_FIXED, ], [ 'sku' => 'simple3', - 'option_id' => 1, 'price' => 30, 'qty' => 1, + 'price_type' => LinkInterface::PRICE_TYPE_FIXED, ] ] ] @@ -261,95 +219,4 @@ public function getProductWithDifferentPrice() ], ]; } - - protected function getFixtureForProductOption(array $data = []) - { - $fixture = $this->fixtureForProductOption; - - // make title different for each call - $fixture['title'] .= ' ' . microtime(true); - - return array_merge($fixture, $data); - } - - protected function getFixtureForProductOptionSelection($data) - { - $fixture = $this->fixtureForProductOptionSelection; - - return array_merge($fixture, $data); - } - - protected function getFixtureForProductCustomOption(array $data = []) - { - $fixture = $this->fixtureForProductCustomOption; - - // make title and sku different for each call - $fixture['title'] .= ' ' . microtime(true); - $fixture['sku'] .= ' ' . microtime(true); - - return array_merge($fixture, $data); - } - - protected function addSpecialPrice(\Magento\Catalog\Model\Product $bundleProduct, $discount) - { - $bundleProduct->setSpecialPrice($discount); - - return $bundleProduct; - } - - protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) - { - $options = []; - - foreach ($optionsData as $optionData) { - $links = []; - $linksData = $optionData['links']; - unset($optionData['links']); - - $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOption($optionData)]) - ->setSku($bundleProduct->getSku()) - ->setOptionid(null); - - foreach ($linksData as $linkData) { - $linkData['option_id'] = $option->getId(); // ??? looks like needed - $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); - } - - $option->setProductLinks($links); - $options[] = $option; - } - - $extension = $bundleProduct->getExtensionAttributes(); - $extension->setBundleProductOptions($options); - $bundleProduct->setExtensionAttributes($extension); - - return $bundleProduct; - } - - protected function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) - { - /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */ - $customOptionFactory = $this->objectManager - ->create(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); - - $options = []; - foreach ($optionsData as $optionData) { - $customOption = $customOptionFactory->create( - [ - 'data' => $this->getFixtureForProductCustomOption($optionData) - ] - ); - $customOption->setProductSku($bundleProduct->getSku()); - $customOption->setOptionId(null); - - $options[] = $customOption; - } - - $bundleProduct->setOptions($options); - $bundleProduct->setCanSaveCustomOptions(true); - - return $bundleProduct; - } } From 4719d15ed1a510afb48ee941bb139dba0f805329 Mon Sep 17 00:00:00 2001 From: aakimov Date: Fri, 28 Oct 2016 17:06:34 +0300 Subject: [PATCH 031/161] MAGETWO-60110: [Github] Shipping Estimation Address is Merged with Customer Default Address during Checkout #6869 --- .../frontend/web/js/view/cart/shipping-estimation.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js index 08641f015f609..3d4612fbe9ec5 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js @@ -50,9 +50,13 @@ define( if (address) { estimatedAddress = address.isEditable() ? addressConverter.quoteAddressToFormAddressData(address) : - addressConverter.quoteAddressToFormAddressData( - addressConverter.addressToEstimationAddress(address) - ); + { + // only the following fields must be used by estimation form data provider + country_id: address.countryId, + region: address.region, + region_id: address.regionId, + postcode: address.postcode + }; checkoutProvider.set( 'shippingAddress', $.extend({}, checkoutProvider.get('shippingAddress'), estimatedAddress) From fe260810330749d036e53aa6d7803ec42688847f Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Fri, 28 Oct 2016 18:25:25 +0300 Subject: [PATCH 032/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - DynamicBundleTests refactoring --- ...undlePrice.php => BundlePriceAbstract.php} | 42 +-- .../DynamicBundlePriceCalculatorTest.php | 9 +- ...ndleWithCatalogPriceRuleCalculatorTest.php | 190 ++++------ ...icBundleWithSpecialPriceCalculatorTest.php | 204 ++++------- ...namicBundleWithTierPriceCalculatorTest.php | 331 +++++++++--------- 5 files changed, 335 insertions(+), 441 deletions(-) rename dev/tests/integration/testsuite/Magento/Bundle/Model/Product/{BundlePrice.php => BundlePriceAbstract.php} (80%) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePrice.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePriceAbstract.php similarity index 80% rename from dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePrice.php rename to dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePriceAbstract.php index f226b514c2304..b71a40cbdb561 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePrice.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePriceAbstract.php @@ -5,12 +5,17 @@ */ namespace Magento\Bundle\Model\Product; +use Zend\Console\Exception\InvalidArgumentException; /** * Abstract class for testing bundle prices */ -abstract class BundlePrice extends \PHPUnit_Framework_TestCase +abstract class BundlePriceAbstract extends \PHPUnit_Framework_TestCase { + const CUSTOM_OPTION_PRICE_TYPE_FIXED = 'fixed'; + + const CUSTOM_OPTION_PRICE_TYPE_PERCENT = 'percent'; + /** @var \Magento\TestFramework\Helper\Bootstrap */ protected $objectManager; @@ -30,7 +35,8 @@ protected function setUp() abstract public function getTestCases(); /** - * @param array $strategyModifiers + * @param $strategyModifiers + * @throws InvalidArgumentException * @return \Magento\Catalog\Api\Data\ProductInterface */ protected function prepareFixture($strategyModifiers) @@ -41,6 +47,10 @@ protected function prepareFixture($strategyModifiers) if (method_exists($this, $modifier['modifierName'])) { array_unshift($modifier['data'], $bundleProduct); $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); + } else { + throw new InvalidArgumentException( + sprintf('Modifier %s does not exists', $modifier['modifierName']) + ); } } @@ -65,11 +75,10 @@ protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduc unset($optionData['links']); $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOption($optionData)]) + ->create(['data' => $optionData]) ->setSku($bundleProduct->getSku()); foreach ($linksData as $linkData) { - $linkData['option_id'] = $option->getId(); $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) ->create(['data' => $linkData]); } @@ -85,18 +94,6 @@ protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduc return $bundleProduct; } - /** - * @param array $fixture - * @return array - */ - private function getFixtureForProductCustomOption(array $fixture = []) - { - $fixture['title'] = 'Custom Option Title ' . microtime(true); - $fixture['sku'] = 'custom_option_sku_' . microtime(true); - - return $fixture; - } - /** * @param \Magento\Catalog\Model\Product $bundleProduct * @param array $optionsData @@ -112,7 +109,7 @@ protected function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct foreach ($optionsData as $optionData) { $customOption = $customOptionFactory->create( [ - 'data' => $this->getFixtureForProductCustomOption($optionData) + 'data' => $optionData ] ); $customOption->setProductSku($bundleProduct->getSku()); @@ -126,15 +123,4 @@ protected function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct return $bundleProduct; } - - /** - * @param array $fixture - * @return array - */ - private function getFixtureForProductOption(array $fixture = []) - { - $fixture['title'] = 'Option title' . microtime(true); - - return $fixture; - } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php index fbb785b43a6e0..81052bd2cef54 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php @@ -10,7 +10,7 @@ * @magentoDataFixture Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php * @magentoAppArea frontend */ -class DynamicBundlePriceCalculatorTest extends BundlePrice +class DynamicBundlePriceCalculatorTest extends BundlePriceAbstract { /** * @param array $strategyModifiers @@ -51,7 +51,7 @@ public function getTestCases() 'maximalPrice' => 10 ] ], - 'Testing price for dynamic bundle product with three simples and differnt qty' => [ + 'Testing price for dynamic bundle product with three simples and different qty' => [ 'strategy' => $this->getProductWithDifferentQty(), 'expectedResults' => [ // min price from simples 3*10 or 30 @@ -60,7 +60,7 @@ public function getTestCases() 'maximalPrice' => 100 ] ], - 'Testing price for dynamic bundle product with four simples and differnt price' => [ + 'Testing price for dynamic bundle product with four simples and different price' => [ 'strategy' => $this->getProductWithDifferentPrice(), 'expectedResults' => [ // 10 @@ -76,6 +76,7 @@ public function getProductWithOneSimple() { $optionsData = [ [ + 'title' => 'op1', 'required' => true, 'type' => 'checkbox', 'links' => [ @@ -99,6 +100,7 @@ public function getProductWithDifferentQty() { $optionsData = [ [ + 'title' => 'op1', 'required' => true, 'type' => 'checkbox', 'links' => [ @@ -130,6 +132,7 @@ public function getProductWithDifferentPrice() { $optionsData = [ [ + 'title' => 'op1', 'required' => true, 'type' => 'checkbox', 'links' => [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php index 5da45a25618a7..fd6554b3b1d08 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php @@ -10,53 +10,17 @@ * @magentoDataFixture Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_with_catalog_rule.php * @magentoAppArea frontend */ -class DynamicBundleWithCatalogPriceRuleCalculatorTest extends \PHPUnit_Framework_TestCase +class DynamicBundleWithCatalogPriceRuleCalculatorTest extends BundlePriceAbstract { - /** @var \Magento\TestFramework\Helper\Bootstrap */ - protected $objectManager; - - /** @var \Magento\Catalog\Api\ProductRepositoryInterface */ - protected $productRepository; - - protected $fixtureForProductOption = [ - 'title' => 'Some title', - 'required' => true, - 'type' => 'checkbox' - ]; - - protected $fixtureForProductOptionSelection = [ - 'sku' => null, // need to set this - 'option_id' => null, // need to set this - 'qty' => 1, - 'is_default' => true, - 'can_change_quantity' => 0 - ]; - - protected function setUp() - { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); - } - /** - * @param $strategyModifiers array - * @param $expectedResults array + * @param array $strategyModifiers + * @param array $expectedResults * @dataProvider getTestCases * @magentoAppIsolation enabled */ public function testPriceForDynamicBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); - - foreach ($strategyModifiers as $modifier) { - if (method_exists($this, $modifier['modifierName'])) { - array_unshift($modifier['data'], $bundleProduct); - $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); - } - } - - $this->productRepository->save($bundleProduct); - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + $bundleProduct = $this->prepareFixture($strategyModifiers); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -89,8 +53,19 @@ public function getTestCases() ] ], + 'Testing price for dynamic bundle product with special price, sub items and catalog rule price' => [ + 'strategy' => $this->getBundleProductConfiguration1(), + 'expectedResults' => [ + // 0.5 * 10 * 0.9 + 'minimalPrice' => 4.5, + + // 0.5 * 10 * 0.9 + 'maximalPrice' => 4.5 + ] + ], + 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #2' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2(), + 'strategy' => $this->getBundleProductConfiguration2(), 'expectedResults' => [ // 0.9 * 2 * 10 'minimalPrice' => 18, @@ -101,7 +76,7 @@ public function getTestCases() ], 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #3' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3(), + 'strategy' => $this->getBundleProductConfiguration3(), 'expectedResults' => [ // 0.9 * 1 * 10 'minimalPrice' => 9, @@ -112,7 +87,7 @@ public function getTestCases() ], 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #4' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4(), + 'strategy' => $this->getBundleProductConfiguration4(), 'expectedResults' => [ // 0.9 * 1 * 10 'minimalPrice' => 9, @@ -123,7 +98,7 @@ public function getTestCases() ], 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #5' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5(), + 'strategy' => $this->getBundleProductConfiguration5(), 'expectedResults' => [ // 0.9 * 1 * 10 'minimalPrice' => 9, @@ -134,7 +109,7 @@ public function getTestCases() ], 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #6' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6(), + 'strategy' => $this->getBundleProductConfiguration6(), 'expectedResults' => [ // 0.9 * 1 * 10 + 0.9 * 1 * 10 'minimalPrice' => 18, @@ -145,7 +120,7 @@ public function getTestCases() ], 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #7' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration7(), + 'strategy' => $this->getBundleProductConfiguration7(), 'expectedResults' => [ // 1 * 0.9 * 10 'minimalPrice' => 9, @@ -156,7 +131,7 @@ public function getTestCases() ], 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #8' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration8(), + 'strategy' => $this->getBundleProductConfiguration8(), 'expectedResults' => [ // 0.9 * 1 * 10 'minimalPrice' => 9, @@ -172,10 +147,13 @@ public function getProductWithSubItemsAndOptionsStrategy() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], ] ], @@ -189,14 +167,17 @@ public function getProductWithSubItemsAndOptionsStrategy() ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1() + public function getBundleProductConfiguration1() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], ] ] @@ -214,15 +195,16 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2() + public function getBundleProductConfiguration2() { $optionsData = [ [ + 'title' => 'Op1', + 'type' => 'checkbox', 'required' => false, 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, 'qty' => 2, ], ] @@ -237,18 +219,20 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3() + public function getBundleProductConfiguration3() { $optionsData = [ [ + 'title' => 'Op1', + 'type' => 'checkbox', + 'required' => true, 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] @@ -263,19 +247,20 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4() + public function getBundleProductConfiguration4() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'multi', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] @@ -290,19 +275,20 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5() + public function getBundleProductConfiguration5() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] @@ -317,33 +303,35 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6() + public function getBundleProductConfiguration6() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] ], [ + 'title' => 'Op2', + 'required' => true, 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 2, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 2, 'qty' => 3, ], ] @@ -358,34 +346,35 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration7() + public function getBundleProductConfiguration7() { $optionsData = [ [ + 'title' => 'Op1', 'required' => false, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] ], [ + 'title' => 'Op2', + 'required' => true, 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 2, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 2, 'qty' => 3, ], ] @@ -400,35 +389,35 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration8() + public function getBundleProductConfiguration8() { $optionsData = [ [ + 'title' => 'Op1', 'required' => false, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] ], [ + 'title' => 'Op2', 'required' => false, 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 2, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 2, 'qty' => 3, ], ] @@ -443,49 +432,14 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - protected function getFixtureForProductOption(array $data = []) - { - $fixture = $this->fixtureForProductOption; - - // make title different for each call - $fixture['title'] .= ' ' . microtime(true); - - return array_merge($fixture, $data); - } - - protected function getFixtureForProductOptionSelection($data) - { - $fixture = $this->fixtureForProductOptionSelection; - - return array_merge($fixture, $data); - } - - protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) + /** + * @param \Magento\Catalog\Model\Product $bundleProduct + * @param int $discount + * @return \Magento\Catalog\Model\Product + */ + protected function addSpecialPrice(\Magento\Catalog\Model\Product $bundleProduct, $discount) { - $options = []; - - foreach ($optionsData as $optionData) { - $links = []; - $linksData = $optionData['links']; - unset($optionData['links']); - - $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOption($optionData)]) - ->setSku($bundleProduct->getSku()) - ->setOptionid(null); - - foreach ($linksData as $linkData) { - $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); - } - - $option->setProductLinks($links); - $options[] = $option; - } - - $extension = $bundleProduct->getExtensionAttributes(); - $extension->setBundleProductOptions($options); - $bundleProduct->setExtensionAttributes($extension); + $bundleProduct->setSpecialPrice($discount); return $bundleProduct; } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php index e0d5273501103..8976da58d0250 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php @@ -10,53 +10,17 @@ * @magentoDataFixture Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php * @magentoAppArea frontend */ -class DynamicBundleWithSpecialPriceCalculatorTest extends \PHPUnit_Framework_TestCase +class DynamicBundleWithSpecialPriceCalculatorTest extends BundlePriceAbstract { - /** @var \Magento\TestFramework\Helper\Bootstrap */ - protected $objectManager; - - /** @var \Magento\Catalog\Api\ProductRepositoryInterface */ - protected $productRepository; - - protected $fixtureForProductOption = [ - 'title' => 'Some title', - 'required' => true, - 'type' => 'checkbox' - ]; - - protected $fixtureForProductOptionSelection = [ - 'sku' => null, // need to set this - 'option_id' => null, // need to set this - 'qty' => 1, - 'is_default' => true, - 'can_change_quantity' => 0 - ]; - - protected function setUp() - { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); - } - /** - * @param $strategyModifiers array - * @param $expectedResults array + * @param array $strategyModifiers + * @param array $expectedResults * @dataProvider getTestCases * @magentoAppIsolation enabled */ public function testPriceForDynamicBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); - - foreach ($strategyModifiers as $modifier) { - if (method_exists($this, $modifier['modifierName'])) { - array_unshift($modifier['data'], $bundleProduct); - $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); - } - } - - $this->productRepository->save($bundleProduct); - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + $bundleProduct = $this->prepareFixture($strategyModifiers); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -79,7 +43,7 @@ public function getTestCases() { return [ 'Testing price for dynamic bundle product with special price and sub items Configuration #1' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1(), + 'strategy' => $this->getBundleConfiguration1(), 'expectedResults' => [ // 0.5 * 10 'minimalPrice' => 5, @@ -88,7 +52,7 @@ public function getTestCases() ] ], 'Testing price for dynamic bundle product with special price and sub items Configuration #2' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2(), + 'strategy' => $this->getBundleConfiguration2(), 'expectedResults' => [ // 0.5 * 2 * 10 'minimalPrice' => 10, @@ -97,7 +61,7 @@ public function getTestCases() ] ], 'Testing price for dynamic bundle product with special price and sub items Configuration #3' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3(), + 'strategy' => $this->getBundleConfiguration3(), 'expectedResults' => [ // 0.5 * 1 * 10 'minimalPrice' => 5, @@ -106,7 +70,7 @@ public function getTestCases() ] ], 'Testing price for dynamic bundle product with special price and sub items Configuration #4' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4(), + 'strategy' => $this->getBundleConfiguration4(), 'expectedResults' => [ // 0.5 * 1 * 10 'minimalPrice' => 5, @@ -115,7 +79,7 @@ public function getTestCases() ] ], 'Testing price for dynamic bundle product with special price and sub items Configuration #5' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5(), + 'strategy' => $this->getBundleConfiguration5(), 'expectedResults' => [ // 0.5 * 1 * 10 'minimalPrice' => 5, @@ -124,7 +88,7 @@ public function getTestCases() ] ], 'Testing price for dynamic bundle product with special price and sub items Configuration #6' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6(), + 'strategy' => $this->getBundleConfiguration6(), 'expectedResults' => [ // 0.5 * (1 * 10 + 1 * 10) 'minimalPrice' => 10, @@ -133,7 +97,7 @@ public function getTestCases() ] ], 'Testing price for dynamic bundle product with special price and sub items Configuration #7' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration7(), + 'strategy' => $this->getBundleConfiguration7(), 'expectedResults' => [ // 0.5 * (1 * 10) 'minimalPrice' => 5, @@ -142,7 +106,7 @@ public function getTestCases() ] ], 'Testing price for dynamic bundle product with special price and sub items Configuration #8' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration8(), + 'strategy' => $this->getBundleConfiguration8(), 'expectedResults' => [ // 0.5 * (1 * 10) 'minimalPrice' => 5, @@ -151,7 +115,7 @@ public function getTestCases() ] ], 'Testing price for dynamic bundle product with sub item product that has special price' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration9(), + 'strategy' => $this->getBundleConfiguration9(), 'expectedResults' => [ // 1 * 3.5 'minimalPrice' => 3.5, @@ -160,7 +124,7 @@ public function getTestCases() ] ], 'Testing price for dynamic bundle product with special price on it and on sub item' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration10(), + 'strategy' => $this->getBundleConfiguration10(), 'expectedResults' => [ // 0.5 * 1 * 3.5 'minimalPrice' => 1.75, @@ -171,14 +135,17 @@ public function getTestCases() ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1() + public function getBundleConfiguration1() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], ] ] @@ -196,15 +163,16 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2() + public function getBundleConfiguration2() { $optionsData = [ [ + 'title' => 'Op1', + 'type' => 'checkbox', 'required' => false, 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, 'qty' => 2, ], ] @@ -223,18 +191,20 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3() + public function getBundleConfiguration3() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] @@ -253,19 +223,20 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4() + public function getBundleConfiguration4() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'multi', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] @@ -284,19 +255,20 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5() + public function getBundleConfiguration5() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] @@ -315,33 +287,35 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6() + public function getBundleConfiguration6() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] ], [ + 'title' => 'Op2', + 'required' => true, 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 2, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 2, 'qty' => 3, ], ] @@ -360,34 +334,35 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration7() + public function getBundleConfiguration7() { $optionsData = [ [ + 'title' => 'Op1', 'required' => false, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] ], [ + 'title' => 'Op2', + 'required' => true, 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 2, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 2, 'qty' => 3, ], ] @@ -406,35 +381,35 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration8() + public function getBundleConfiguration8() { $optionsData = [ [ + 'title' => 'Op1', 'required' => false, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] ], [ + 'title' => 'Op2', 'required' => false, 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 2, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 2, 'qty' => 3, ], ] @@ -453,19 +428,21 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration9() + public function getBundleConfiguration9() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, + 'qty' => 1, ], ] ] @@ -483,19 +460,20 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration10() + public function getBundleConfiguration10() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] @@ -518,23 +496,11 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - protected function getFixtureForProductOption(array $data = []) - { - $fixture = $this->fixtureForProductOption; - - // make title different for each call - $fixture['title'] .= ' ' . microtime(true); - - return array_merge($fixture, $data); - } - - protected function getFixtureForProductOptionSelection($data) - { - $fixture = $this->fixtureForProductOptionSelection; - - return array_merge($fixture, $data); - } - + /** + * @param \Magento\Catalog\Model\Product $bundleProduct + * @param int $discount + * @return \Magento\Catalog\Model\Product + */ protected function addSpecialPrice(\Magento\Catalog\Model\Product $bundleProduct, $discount) { $bundleProduct->setSpecialPrice($discount); @@ -542,6 +508,12 @@ protected function addSpecialPrice(\Magento\Catalog\Model\Product $bundleProduct return $bundleProduct; } + /** + * @param \Magento\Catalog\Model\Product $bundleProduct + * @param string $sku + * @param int $price + * @return \Magento\Catalog\Model\Product + */ protected function addSpecialPriceForSimple(\Magento\Catalog\Model\Product $bundleProduct, $sku, $price) { $simple = $this->productRepository->get($sku, false, null, true); @@ -550,34 +522,4 @@ protected function addSpecialPriceForSimple(\Magento\Catalog\Model\Product $bund return $bundleProduct; } - - protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) - { - $options = []; - - foreach ($optionsData as $optionData) { - $links = []; - $linksData = $optionData['links']; - unset($optionData['links']); - - $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOption($optionData)]) - ->setSku($bundleProduct->getSku()) - ->setOptionid(null); - - foreach ($linksData as $linkData) { - $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); - } - - $option->setProductLinks($links); - $options[] = $option; - } - - $extension = $bundleProduct->getExtensionAttributes(); - $extension->setBundleProductOptions($options); - $bundleProduct->setExtensionAttributes($extension); - - return $bundleProduct; - } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php index 801dba66a8e86..9612279da292e 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php @@ -6,50 +6,20 @@ namespace Magento\Bundle\Model\Product; -use \Magento\Catalog\Api\ProductRepositoryInterface; use \Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory; /** * @magentoDataFixture Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php * @magentoAppArea frontend */ -class DynamicBundleWithTierPriceCalculatorTest extends \PHPUnit_Framework_TestCase +class DynamicBundleWithTierPriceCalculatorTest extends BundlePriceAbstract { - /** @var \Magento\TestFramework\Helper\Bootstrap */ - private $objectManager; - - /** @var ProductRepositoryInterface */ - private $productRepository; - /** @var ProductTierPriceInterfaceFactory */ private $tierPriceFactory; - private $fixtureForTierPrice = [ - 'data' => [ - 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, - 'qty' => 1, - 'value' => 50 - ] - ]; - - private $fixtureForProductOption = [ - 'title' => 'Some title', - 'required' => true, - 'type' => 'checkbox' - ]; - - private $fixtureForProductOptionSelection = [ - 'sku' => null, // need to set this - 'option_id' => null, // need to set this - 'qty' => 1, - 'is_default' => true, - 'can_change_quantity' => 0 - ]; - protected function setUp() { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class); + parent::setUp(); $this->tierPriceFactory = $this->objectManager->create(ProductTierPriceInterfaceFactory::class); } @@ -61,18 +31,7 @@ protected function setUp() */ public function testPriceForDynamicBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); - $this->addTierPrice($bundleProduct); - - foreach ($strategyModifiers as $modifier) { - if (method_exists($this, $modifier['modifierName'])) { - array_unshift($modifier['data'], $bundleProduct); - $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); - } - } - - $this->productRepository->save($bundleProduct); - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + $bundleProduct = $this->prepareFixture($strategyModifiers); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -95,7 +54,7 @@ public function getTestCases() { return [ 'Testing product price with tier price and sub items Configuration #1' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration1(), + 'strategy' => $this->getBundleConfiguration1(), 'expectedResults' => [ // 0.5 * 10 'minimalPrice' => 5, @@ -104,7 +63,7 @@ public function getTestCases() ] ], 'Testing product price with tier price and sub items Configuration #2' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration2(), + 'strategy' => $this->getBundleConfiguration2(), 'expectedResults' => [ // 0.5 * 2 * 10 'minimalPrice' => 10, @@ -113,7 +72,7 @@ public function getTestCases() ] ], 'Testing product price with tier price and sub items Configuration #3' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration3(), + 'strategy' => $this->getBundleConfiguration3(), 'expectedResults' => [ // 0.5 * 1 * 10 'minimalPrice' => 5, @@ -122,7 +81,7 @@ public function getTestCases() ] ], 'Testing product price with tier price and sub items Configuration #4' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration4(), + 'strategy' => $this->getBundleConfiguration4(), 'expectedResults' => [ // 0.5 * 1 * 10 'minimalPrice' => 5, @@ -131,7 +90,7 @@ public function getTestCases() ] ], 'Testing product price with tier price and sub items Configuration #5' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration5(), + 'strategy' => $this->getBundleConfiguration5(), 'expectedResults' => [ // 0.5 * 1 * 10 'minimalPrice' => 5, @@ -140,7 +99,7 @@ public function getTestCases() ] ], 'Testing product price with tier price and sub items Configuration #6' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration6(), + 'strategy' => $this->getBundleConfiguration6(), 'expectedResults' => [ // 0.5 * (1 * 10 + 1 * 10) 'minimalPrice' => 10, @@ -149,7 +108,7 @@ public function getTestCases() ] ], 'Testing product price with tier price and sub items Configuration #7' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration7(), + 'strategy' => $this->getBundleConfiguration7(), 'expectedResults' => [ // 0.5 * (1 * 10) 'minimalPrice' => 5, @@ -158,7 +117,7 @@ public function getTestCases() ] ], 'Testing product price with tier price and sub items Configuration #8' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration8(), + 'strategy' => $this->getBundleConfiguration8(), 'expectedResults' => [ // 0.5 * (1 * 10) 'minimalPrice' => 5, @@ -167,7 +126,7 @@ public function getTestCases() ] ], 'Testing price for dynamic bundle product with tier price on it and on sub item' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategyConfiguration10(), + 'strategy' => $this->getBundleConfiguration10(), 'expectedResults' => [ // 0.5 * 1 * 2.5 'minimalPrice' => 1.25, @@ -178,41 +137,33 @@ public function getTestCases() ]; } - public function getProductWithSubItemsAndOptionsStrategy() + public function getBundleConfiguration1() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], ] - ], - ]; - - return [ - [ - 'modifierName' => 'addSimpleProduct', - 'data' => [$optionsData] - ], + ] ]; - } - public function getProductWithSubItemsAndOptionsStrategyConfiguration1() - { - $optionsData = [ - [ - 'links' => [ - [ - 'sku' => 'simple1', - 'option_id' => 1, - ], - ] - ] + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 ]; return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -220,22 +171,33 @@ public function getProductWithSubItemsAndOptionsStrategyConfiguration1() ]; } - public function getProductWithSubItemsAndOptionsStrategyConfiguration2() + public function getBundleConfiguration2() { $optionsData = [ [ + 'title' => 'Op1', + 'type' => 'checkbox', 'required' => false, 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, 'qty' => 2, ], ] ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -243,25 +205,37 @@ public function getProductWithSubItemsAndOptionsStrategyConfiguration2() ]; } - public function getProductWithSubItemsAndOptionsStrategyConfiguration3() + public function getBundleConfiguration3() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -269,26 +243,37 @@ public function getProductWithSubItemsAndOptionsStrategyConfiguration3() ]; } - public function getProductWithSubItemsAndOptionsStrategyConfiguration4() + public function getBundleConfiguration4() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'multi', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -296,26 +281,37 @@ public function getProductWithSubItemsAndOptionsStrategyConfiguration4() ]; } - public function getProductWithSubItemsAndOptionsStrategyConfiguration5() + public function getBundleConfiguration5() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -323,40 +319,52 @@ public function getProductWithSubItemsAndOptionsStrategyConfiguration5() ]; } - public function getProductWithSubItemsAndOptionsStrategyConfiguration6() + public function getBundleConfiguration6() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] ], [ + 'title' => 'Op2', + 'required' => true, 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 2, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 2, 'qty' => 3, ], ] ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -364,41 +372,52 @@ public function getProductWithSubItemsAndOptionsStrategyConfiguration6() ]; } - public function getProductWithSubItemsAndOptionsStrategyConfiguration7() + public function getBundleConfiguration7() { $optionsData = [ [ + 'title' => 'Op1', 'required' => false, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] ], [ + 'title' => 'Op2', + 'required' => true, 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 2, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 2, 'qty' => 3, ], ] ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -406,42 +425,52 @@ public function getProductWithSubItemsAndOptionsStrategyConfiguration7() ]; } - public function getProductWithSubItemsAndOptionsStrategyConfiguration8() + public function getBundleConfiguration8() { $optionsData = [ [ + 'title' => 'Op1', 'required' => false, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] ], [ + 'title' => 'Op2', 'required' => false, 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 2, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 2, 'qty' => 3, ], ] ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -449,29 +478,46 @@ public function getProductWithSubItemsAndOptionsStrategyConfiguration8() ]; } - public function getProductWithSubItemsAndOptionsStrategyConfiguration10() + public function getBundleConfiguration10() { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, ], [ 'sku' => 'simple2', - 'option_id' => 1, 'qty' => 3, ], ] ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + + $tierPriceSimpleProductData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 2.5 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addTierPriceForSimple', - 'data' => ['simple1', 2.5] + 'data' => ['simple1', $tierPriceSimpleProductData] ], [ 'modifierName' => 'addSimpleProduct', @@ -480,70 +526,33 @@ public function getProductWithSubItemsAndOptionsStrategyConfiguration10() ]; } - protected function getFixtureForProductOption(array $data = []) - { - $fixture = $this->fixtureForProductOption; - - // make title different for each call - $fixture['title'] .= ' ' . microtime(true); - - return array_merge($fixture, $data); - } - - protected function getFixtureForProductOptionSelection($data) + /** + * @param \Magento\Catalog\Model\Product $product + * @param array $tirePriceData + * @return \Magento\Catalog\Model\Product + */ + protected function addTierPrice(\Magento\Catalog\Model\Product $product, $tirePriceData) { - $fixture = $this->fixtureForProductOptionSelection; + $tierPrice = $this->tierPriceFactory->create([ + 'data' => $tirePriceData + ]); + $product->setTierPrices([$tierPrice]); - return array_merge($fixture, $data); + return $product; } - protected function addTierPriceForSimple(\Magento\Catalog\Model\Product $bundleProduct, $sku, $price) + /** + * @param \Magento\Catalog\Model\Product $bundleProduct + * @param string $sku + * @param array $tirePriceData + * @return \Magento\Catalog\Model\Product + */ + protected function addTierPriceForSimple(\Magento\Catalog\Model\Product $bundleProduct, $sku, $tirePriceData) { $simple = $this->productRepository->get($sku, false, null, true); - $fixtureForTierPrice = $this->fixtureForTierPrice; - $fixtureForTierPrice['data']['value'] = $price; - $tierPrice = $this->tierPriceFactory->create($fixtureForTierPrice); - $simple->setTierPrices([$tierPrice]); + $simple = $this->addTierPrice($simple, $tirePriceData); $this->productRepository->save($simple); return $bundleProduct; } - - protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) - { - $options = []; - - foreach ($optionsData as $optionData) { - $links = []; - $linksData = $optionData['links']; - unset($optionData['links']); - - $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOption($optionData)]) - ->setSku($bundleProduct->getSku()) - ->setOptionid(null); - - foreach ($linksData as $linkData) { - $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); - } - - $option->setProductLinks($links); - $options[] = $option; - } - - $extension = $bundleProduct->getExtensionAttributes(); - $extension->setBundleProductOptions($options); - $bundleProduct->setExtensionAttributes($extension); - - return $bundleProduct; - } - - private function addTierPrice(\Magento\Catalog\Model\Product $bundleProduct) - { - $tierPrice = $this->tierPriceFactory->create($this->fixtureForTierPrice); - $bundleProduct->setTierPrices([$tierPrice]); - - return $bundleProduct; - } } From a25154ec416f55f4e6f3058c447617f9d6da2b77 Mon Sep 17 00:00:00 2001 From: Vitaliy Goncharenko Date: Mon, 31 Oct 2016 10:59:57 +0200 Subject: [PATCH 033/161] MAGETWO-53583: "Use Default" checkbox is checked again after saving empty fields (description, name, etc) - changes after CR --- .../Entity/Attribute/AbstractAttribute.php | 21 +++++---- .../Eav/Model/ResourceModel/UpdateHandler.php | 44 +++++++++---------- .../Model/ResourceModel/UpdateHandlerTest.php | 6 +-- 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index 2804250a35c6e..ba6e670ee9642 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -116,7 +116,14 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens * * @var array */ - private $emptyStringTypes = ['int', 'decimal', 'datetime', 'varchar', 'text', 'static']; + private $emptyStringTypes = [ + 'int', + 'decimal', + 'datetime', + 'varchar', + 'text', + 'static', + ]; /** * @param \Magento\Framework\Model\Context $context @@ -607,18 +614,14 @@ protected function _getDefaultSourceModel() * Check if Value is empty. * * @param array|null|bool|int|float|string $value - * @param bool $strictEmptyStringType [optional] Flag for allow empty string as a possible value for String. - * By default set to TRUE = disallow empty string. * @return bool */ - public function isValueEmpty($value, $strictEmptyStringType = true) + public function isValueEmpty($value) { - $isInEmptyStringTypes = $strictEmptyStringType ? $this->isInEmptyStringTypes() : !$this->isInEmptyStringTypes(); - return (is_array($value) && count($value) == 0) - || $value === null - || ($value === false && $this->getBackend()->getType() != 'int') - || ($value === '' && $isInEmptyStringTypes); + || $value === null + || ($value === false && $this->getBackend()->getType() != 'int') + || ($value === '' && $this->isInEmptyStringTypes()); } /** diff --git a/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php b/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php index 4494d66b42fc6..bcaf11aaf5532 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php +++ b/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php @@ -125,26 +125,17 @@ public function execute($entityType, $entityData, $arguments = []) : null; // @todo verify is it normal to not have attributer_set_id $snapshot = $this->readSnapshot->execute($entityType, $entityDataForSnapshot); foreach ($this->getAttributes($entityType, $attributeSetId) as $attribute) { - if ($attribute->isStatic()) { - continue; - } $code = $attribute->getAttributeCode(); - /** - * Only scalar values can be stored in generic tables - */ - if (isset($entityData[$code]) && !is_scalar($entityData[$code])) { - continue; - } - /** - * Only changed attributes need to handle update process - */ - if (!array_key_exists($code, $entityData)) { + $isAllowedValueType = array_key_exists($code, $entityData) + && (is_scalar($entityData[$code]) || $entityData[$code] === null); + + if ($attribute->isStatic() || !$isAllowedValueType) { continue; } $newValue = $entityData[$code]; - $isValueEmpty = $attribute->isValueEmpty($newValue, false); - $isAllowedEmptyTextValue = $attribute->isAllowedEmptyTextValue($newValue); + $isValueEmpty = $attribute->isValueEmpty($newValue); + $isAllowedEmptyStringValue = $attribute->isAllowedEmptyTextValue($newValue); if (array_key_exists($code, $snapshot)) { $snapshotValue = $snapshot[$code]; @@ -155,25 +146,32 @@ public function execute($entityType, $entityData, $arguments = []) continue; } - if ($isValueEmpty && !$isAllowedEmptyTextValue) { - $this->attributePersistor->registerDelete( - $entityType, - $entityData[$metadata->getLinkField()], - $code - ); - } elseif ((!$isValueEmpty || $isAllowedEmptyTextValue) && $snapshotValue !== $newValue) { + if (!$isValueEmpty || $isAllowedEmptyStringValue) { + /** + * NOT Updated value for attributes not need to update + */ + if ($snapshotValue === $newValue) { + continue; + } + $this->attributePersistor->registerUpdate( $entityType, $entityData[$metadata->getLinkField()], $code, $newValue ); + } else { + $this->attributePersistor->registerDelete( + $entityType, + $entityData[$metadata->getLinkField()], + $code + ); } } else { /** * Only not empty value of attribute is insertable */ - if (!$isValueEmpty || $isAllowedEmptyTextValue) { + if (!$isValueEmpty || $isAllowedEmptyStringValue) { $this->attributePersistor->registerInsert( $entityType, $entityData[$metadata->getLinkField()], diff --git a/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php b/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php index cd110713711e0..eb30a7d0168c6 100644 --- a/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php +++ b/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php @@ -47,7 +47,7 @@ public function testExecuteProcessForAllStores($code, $snapshotValue, $newValue, $resultEntity->setStoreId(0); $resultEntity->load(1); - $this->assertTrue($expected === $resultEntity->getData($code)); + $this->assertSame($expected, $resultEntity->getData($code)); } /** @@ -91,7 +91,7 @@ public function testExecuteProcessForCustomStore($code, $snapshotValue, $newValu $resultEntity->setStoreId($store->getId()); $resultEntity->load(1); - $this->assertTrue($expected === $resultEntity->getData($code)); + $this->assertSame($expected, $resultEntity->getData($code)); } /** @@ -174,7 +174,7 @@ public function testExecuteProcessForCustomAttributeInCustomStore( $expected = $optionIds[$expected]; } - $this->assertTrue($expected === $resultEntity->getData($code)); + $this->assertSame($expected, $resultEntity->getData($code)); } /** From 6c44491452e15e1c4b7eff51aa4d93f09f5b656e Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Mon, 31 Oct 2016 11:05:28 +0200 Subject: [PATCH 034/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - FixedBundleTests refactoring --- .../FixedBundlePriceCalculatorTest.php | 6 +- ...ndleWithCatalogPriceRuleCalculatorTest.php | 234 ++++-------- ...edBundleWithSpecialPriceCalculatorTest.php | 234 ++++-------- ...FixedBundleWithTierPriceCalculatorTest.php | 350 ++++++++---------- 4 files changed, 313 insertions(+), 511 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php index 66ae6a975a72c..63d8e3ba060f0 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php @@ -12,7 +12,7 @@ * @magentoDataFixture Magento/Bundle/_files/PriceCalculator/fixed_bundle_product.php * @magentoAppArea frontend */ -class FixedBundlePriceCalculatorTest extends BundlePrice +class FixedBundlePriceCalculatorTest extends BundlePriceAbstract { /** * @param $strategyModifiers array @@ -88,6 +88,7 @@ public function getProductWithOneSimple() { $optionsData = [ [ + 'title' => 'Op1', 'required' => true, 'type' => 'checkbox', 'links' => [ @@ -113,6 +114,7 @@ public function getProductWithDifferentQty() { $optionsData = [ [ + 'title' => 'Op1', 'required' => true, 'type' => 'checkbox', 'links' => [ @@ -150,6 +152,7 @@ public function getProductWithSamePrice() { $optionsData = [ [ + 'title' => 'Op1', 'required' => true, 'type' => 'checkbox', 'links' => [ @@ -187,6 +190,7 @@ public function getProductWithDifferentPrice() { $optionsData = [ [ + 'title' => 'Op1', 'required' => true, 'type' => 'checkbox', 'links' => [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php index f5c72da722639..88d9be5e7a9fb 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php @@ -12,72 +12,17 @@ * @magentoDataFixture Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_with_catalog_rule.php * @magentoAppArea frontend */ -class FixedBundleWithCatalogPriceRuleCalculatorTest extends \PHPUnit_Framework_TestCase +class FixedBundleWithCatalogPriceRuleCalculatorTest extends BundlePriceAbstract { - /** @var \Magento\TestFramework\Helper\Bootstrap */ - protected $objectManager; - - /** @var \Magento\Catalog\Api\ProductRepositoryInterface */ - protected $productRepository; - - const CUSTOM_OPTION_PRICE_TYPE_FIXED = 'fixed'; - - const CUSTOM_OPTION_PRICE_TYPE_PERCENT = 'percent'; - - protected $fixtureForProductOption = [ - 'title' => 'Some title', - 'required' => true, - 'type' => 'checkbox' - ]; - - protected $fixtureForProductOptionSelection = [ - 'sku' => null, // need to set this - 'option_id' => null, // need to set this - 'qty' => 1, - 'is_default' => true, - 'price' => null, // need to set this - 'price_type' => LinkInterface::PRICE_TYPE_FIXED, - 'can_change_quantity' => 0 - ]; - - protected $fixtureForProductCustomOption = [ - 'option_id' => null, - 'previous_group' => 'text', - 'title' => 'Test Field', - 'type' => 'field', - 'is_require' => 1, - 'sort_order' => 0, - 'price' => 100, - 'price_type' => 'fixed', - 'sku' => '1-text', - 'max_characters' => 100, - ]; - - protected function setUp() - { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); - } - /** - * @param $strategyModifiers array - * @param $expectedResults array + * @param array $strategyModifiers + * @param array $expectedResults * @dataProvider getTestCases * @magentoAppIsolation enabled */ public function testPriceForFixedBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); - - foreach ($strategyModifiers as $modifier) { - if (method_exists($this, $modifier['modifierName'])) { - array_unshift($modifier['data'], $bundleProduct); - $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); - } - } - - $this->productRepository->save($bundleProduct); - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + $bundleProduct = $this->prepareFixture($strategyModifiers); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -600,10 +545,13 @@ public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $ { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 20, 'price_type' => $selectionsPriceType ], @@ -613,7 +561,12 @@ public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $ $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; @@ -633,10 +586,13 @@ public function getProductSubItemsAndOptionsStrategyConfiguration1($selectionsPr { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 20, 'price_type' => $selectionsPriceType ], @@ -646,7 +602,12 @@ public function getProductSubItemsAndOptionsStrategyConfiguration1($selectionsPr $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; @@ -666,11 +627,12 @@ public function getProductSubItemsAndOptionsStrategyConfiguration2($selectionsPr { $optionsData = [ [ + 'title' => 'Op1', + 'type' => 'checkbox', 'required' => false, 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, 'price' => 20, 'qty' => 2, 'price_type' => $selectionsPriceType @@ -681,7 +643,12 @@ public function getProductSubItemsAndOptionsStrategyConfiguration2($selectionsPr $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; @@ -701,16 +668,18 @@ public function getProductSubItemsAndOptionsStrategyConfiguration3($selectionsPr { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 40, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 10, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -721,7 +690,12 @@ public function getProductSubItemsAndOptionsStrategyConfiguration3($selectionsPr $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; @@ -741,17 +715,18 @@ public function getProductSubItemsAndOptionsStrategyConfiguration4($selectionsPr { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'multi', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 40, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 15, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -762,7 +737,12 @@ public function getProductSubItemsAndOptionsStrategyConfiguration4($selectionsPr $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; @@ -782,17 +762,18 @@ public function getProductSubItemsAndOptionsStrategyConfiguration5($selectionsPr { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 40, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 15, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -803,7 +784,12 @@ public function getProductSubItemsAndOptionsStrategyConfiguration5($selectionsPr $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; @@ -823,17 +809,18 @@ public function getProductSubItemsAndOptionsStrategyConfiguration6($selectionsPr { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 40, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 15, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -841,17 +828,18 @@ public function getProductSubItemsAndOptionsStrategyConfiguration6($selectionsPr ] ], [ + 'title' => 'Op2', + 'required' => true, 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 2, + 'qty' => 1, 'price' => 20, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 2, 'price' => 10, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -862,7 +850,12 @@ public function getProductSubItemsAndOptionsStrategyConfiguration6($selectionsPr $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; @@ -877,87 +870,4 @@ public function getProductSubItemsAndOptionsStrategyConfiguration6($selectionsPr ], ]; } - - protected function getFixtureForProductOption(array $data = []) - { - $fixture = $this->fixtureForProductOption; - - // make title different for each call - $fixture['title'] .= ' ' . microtime(true); - - return array_merge($fixture, $data); - } - - protected function getFixtureForProductOptionSelection($data) - { - $fixture = $this->fixtureForProductOptionSelection; - - return array_merge($fixture, $data); - } - - protected function getFixtureForProductCustomOption(array $data = []) - { - $fixture = $this->fixtureForProductCustomOption; - - // make title and sku different for each call - $fixture['title'] .= ' ' . microtime(true); - $fixture['sku'] .= ' ' . microtime(true); - - return array_merge($fixture, $data); - } - - protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) - { - $options = []; - - foreach ($optionsData as $optionData) { - $links = []; - $linksData = $optionData['links']; - unset($optionData['links']); - - $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOption($optionData)]) - ->setSku($bundleProduct->getSku()) - ->setOptionid(null); - - foreach ($linksData as $linkData) { - $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); - } - - $option->setProductLinks($links); - $options[] = $option; - } - - $extension = $bundleProduct->getExtensionAttributes(); - $extension->setBundleProductOptions($options); - $bundleProduct->setExtensionAttributes($extension); - - return $bundleProduct; - } - - protected function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) - { - /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */ - $customOptionFactory = $this->objectManager - ->create(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); - - $options = []; - foreach ($optionsData as $optionData) { - $customOption = $customOptionFactory->create( - [ - 'data' => $this->getFixtureForProductCustomOption($optionData) - ] - ); - $customOption->setProductSku($bundleProduct->getSku()); - $customOption->setOptionId(null); - - $options[] = $customOption; - } - - $bundleProduct->setOptions($options); - $bundleProduct->setCanSaveCustomOptions(true); - - return $bundleProduct; - } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php index 6b0572a0b1164..e178087e0cfc7 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php @@ -12,72 +12,17 @@ * @magentoDataFixture Magento/Bundle/_files/PriceCalculator/fixed_bundle_product.php * @magentoAppArea frontend */ -class FixedBundleWithSpecialPriceCalculatorTest extends \PHPUnit_Framework_TestCase +class FixedBundleWithSpecialPriceCalculatorTest extends BundlePriceAbstract { - /** @var \Magento\TestFramework\Helper\Bootstrap */ - protected $objectManager; - - /** @var \Magento\Catalog\Api\ProductRepositoryInterface */ - protected $productRepository; - - const CUSTOM_OPTION_PRICE_TYPE_FIXED = 'fixed'; - - const CUSTOM_OPTION_PRICE_TYPE_PERCENT = 'percent'; - - protected $fixtureForProductOption = [ - 'title' => 'Some title', - 'required' => true, - 'type' => 'checkbox' - ]; - - protected $fixtureForProductOptionSelection = [ - 'sku' => null, // need to set this - 'option_id' => null, // need to set this - 'qty' => 1, - 'is_default' => true, - 'price' => null, // need to set this - 'price_type' => LinkInterface::PRICE_TYPE_FIXED, - 'can_change_quantity' => 0 - ]; - - protected $fixtureForProductCustomOption = [ - 'option_id' => null, - 'previous_group' => 'text', - 'title' => 'Test Field', - 'type' => 'field', - 'is_require' => 1, - 'sort_order' => 0, - 'price' => 100, - 'price_type' => 'fixed', - 'sku' => '1-text', - 'max_characters' => 100, - ]; - - protected function setUp() - { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); - } - /** - * @param $strategyModifiers array - * @param $expectedResults array + * @param array $strategyModifiers + * @param array $expectedResults * @dataProvider getTestCases * @magentoAppIsolation enabled */ public function testPriceForFixedBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); - - foreach ($strategyModifiers as $modifier) { - if (method_exists($this, $modifier['modifierName'])) { - array_unshift($modifier['data'], $bundleProduct); - $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); - } - } - - $this->productRepository->save($bundleProduct); - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + $bundleProduct = $this->prepareFixture($strategyModifiers); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -624,10 +569,13 @@ public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $ { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 20, 'price_type' => $selectionsPriceType ], @@ -637,7 +585,12 @@ public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $ $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; @@ -659,10 +612,13 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ) { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 20, 'price_type' => $selectionsPriceType ], @@ -672,7 +628,12 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; @@ -698,11 +659,12 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ) { $optionsData = [ [ + 'title' => 'Op1', + 'type' => 'checkbox', 'required' => false, 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, 'price' => 20, 'qty' => 2, 'price_type' => $selectionsPriceType @@ -713,7 +675,12 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; @@ -739,16 +706,18 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ) { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 40, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 10, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -759,7 +728,12 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; @@ -785,17 +759,18 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ) { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'multi', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 40, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 15, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -806,7 +781,12 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; @@ -832,17 +812,18 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ) { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 40, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 15, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -853,7 +834,12 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; @@ -879,17 +865,18 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ) { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 40, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 15, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -897,17 +884,18 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ] ], [ + 'title' => 'Op2', + 'required' => true, 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 2, + 'qty' => 1, 'price' => 20, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 2, 'price' => 10, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -918,7 +906,12 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; @@ -938,93 +931,10 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - protected function getFixtureForProductOption(array $data = []) - { - $fixture = $this->fixtureForProductOption; - - // make title different for each call - $fixture['title'] .= ' ' . microtime(true); - - return array_merge($fixture, $data); - } - - protected function getFixtureForProductOptionSelection($data) - { - $fixture = $this->fixtureForProductOptionSelection; - - return array_merge($fixture, $data); - } - - protected function getFixtureForProductCustomOption(array $data = []) - { - $fixture = $this->fixtureForProductCustomOption; - - // make title and sku different for each call - $fixture['title'] .= ' ' . microtime(true); - $fixture['sku'] .= ' ' . microtime(true); - - return array_merge($fixture, $data); - } - protected function addSpecialPrice(\Magento\Catalog\Model\Product $bundleProduct, $discount) { $bundleProduct->setSpecialPrice($discount); return $bundleProduct; } - - protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) - { - $options = []; - - foreach ($optionsData as $optionData) { - $links = []; - $linksData = $optionData['links']; - unset($optionData['links']); - - $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOption($optionData)]) - ->setSku($bundleProduct->getSku()) - ->setOptionid(null); - - foreach ($linksData as $linkData) { - $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); - } - - $option->setProductLinks($links); - $options[] = $option; - } - - $extension = $bundleProduct->getExtensionAttributes(); - $extension->setBundleProductOptions($options); - $bundleProduct->setExtensionAttributes($extension); - - return $bundleProduct; - } - - protected function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) - { - /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */ - $customOptionFactory = $this->objectManager - ->create(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); - - $options = []; - foreach ($optionsData as $optionData) { - $customOption = $customOptionFactory->create( - [ - 'data' => $this->getFixtureForProductCustomOption($optionData) - ] - ); - $customOption->setProductSku($bundleProduct->getSku()); - $customOption->setOptionId(null); - - $options[] = $customOption; - } - - $bundleProduct->setOptions($options); - $bundleProduct->setCanSaveCustomOptions(true); - - return $bundleProduct; - } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php index 36482b9b83342..d9e9359c59c43 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php @@ -7,7 +7,6 @@ namespace Magento\Bundle\Model\Product; use \Magento\Bundle\Api\Data\LinkInterface; -use \Magento\Catalog\Api\ProductRepositoryInterface; use \Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory; /** @@ -16,63 +15,14 @@ * @magentoDataFixture Magento/Bundle/_files/PriceCalculator/fixed_bundle_product.php * @magentoAppArea frontend */ -class FixedBundleWithTierPriceCalculatorTest extends \PHPUnit_Framework_TestCase +class FixedBundleWithTierPriceCalculatorTest extends BundlePriceAbstract { - - const CUSTOM_OPTION_PRICE_TYPE_FIXED = 'fixed'; - - const CUSTOM_OPTION_PRICE_TYPE_PERCENT = 'percent'; - - /** @var \Magento\TestFramework\Helper\Bootstrap */ - private $objectManager; - - /** @var ProductRepositoryInterface */ - private $productRepository; - /** @var ProductTierPriceInterfaceFactory */ private $tierPriceFactory; - private $fixtureForTierPrice = [ - 'data' => [ - 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, - 'qty' => 1, - 'value' => 50 - ] - ]; - - private $fixtureForProductOption = [ - 'title' => 'Some title', - 'required' => true, - 'type' => 'checkbox' - ]; - - private $fixtureForProductOptionSelection = [ - 'sku' => null, // need to set this - 'option_id' => null, // need to set this - 'qty' => 1, - 'is_default' => true, - 'price' => null, // need to set this - 'price_type' => LinkInterface::PRICE_TYPE_FIXED, - 'can_change_quantity' => 0 - ]; - - private $fixtureForProductCustomOption = [ - 'option_id' => null, - 'previous_group' => 'text', - 'title' => 'Test Field', - 'type' => 'field', - 'is_require' => 1, - 'sort_order' => 0, - 'price' => 100, - 'price_type' => 'fixed', - 'sku' => 'for-custom-option', - 'max_characters' => 100, - ]; - protected function setUp() { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class); + parent::setUp(); $this->tierPriceFactory = $this->objectManager->create(ProductTierPriceInterfaceFactory::class); } @@ -84,17 +34,7 @@ protected function setUp() */ public function testPriceForFixedBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); - $this->addTierPrice($bundleProduct); - foreach ($strategyModifiers as $modifier) { - if (method_exists($this, $modifier['modifierName'])) { - array_unshift($modifier['data'], $bundleProduct); - $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); - } - } - - $this->productRepository->save($bundleProduct); - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + $bundleProduct = $this->prepareFixture($strategyModifiers); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -121,7 +61,6 @@ public function getTestCases() { return [ - 'Testing product price with tier price and without any sub items and options' => [ 'strategy' => $this->getEmptyProduct(), 'expectedResults' => [ @@ -175,20 +114,6 @@ public function getTestCases() ] ], - 'Testing product price with tier price, fixed sub items and percent options Configuration #1' => [ - 'strategy' => $this->getProductConfiguration1( - LinkInterface::PRICE_TYPE_FIXED, - self::CUSTOM_OPTION_PRICE_TYPE_PERCENT - ), - 'expectedResults' => [ - // 0.5 * (110 + 1 * 20 + 110 * 1) - 'minimalPrice' => 120, - - // 0.5 * (110 + 1 * 20 + 110 * 1) - 'maximalPrice' => 120 - ] - ], - 'Testing product price with tier price, percent sub items and fixed options Configuration #1' => [ 'strategy' => $this->getProductConfiguration1( LinkInterface::PRICE_TYPE_PERCENT, @@ -488,17 +413,31 @@ public function getTestCases() public function getEmptyProduct() { - return []; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ] + ]; } public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 20, 'price_type' => $selectionsPriceType ], @@ -508,11 +447,26 @@ public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $ $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -528,10 +482,13 @@ public function getProductConfiguration1($selectionsPriceType, $customOptionsPri { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 20, 'price_type' => $selectionsPriceType ], @@ -541,11 +498,26 @@ public function getProductConfiguration1($selectionsPriceType, $customOptionsPri $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -561,11 +533,12 @@ public function getProductConfiguration2($selectionsPriceType, $customOptionsPri { $optionsData = [ [ + 'title' => 'Op1', + 'type' => 'checkbox', 'required' => false, 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, 'price' => 20, 'qty' => 2, 'price_type' => $selectionsPriceType @@ -576,11 +549,26 @@ public function getProductConfiguration2($selectionsPriceType, $customOptionsPri $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -596,16 +584,18 @@ public function getProductConfiguration3($selectionsPriceType, $customOptionsPri { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, + 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 40, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 10, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -616,11 +606,26 @@ public function getProductConfiguration3($selectionsPriceType, $customOptionsPri $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -636,17 +641,18 @@ public function getProductConfiguration4($selectionsPriceType, $customOptionsPri { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'multi', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 40, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 15, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -657,11 +663,26 @@ public function getProductConfiguration4($selectionsPriceType, $customOptionsPri $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -677,17 +698,18 @@ public function getProductConfiguration5($selectionsPriceType, $customOptionsPri { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 40, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 15, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -698,11 +720,26 @@ public function getProductConfiguration5($selectionsPriceType, $customOptionsPri $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -718,17 +755,18 @@ public function getProductConfiguration6($selectionsPriceType, $customOptionsPri { $optionsData = [ [ + 'title' => 'Op1', + 'required' => true, 'type' => 'radio', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 1, + 'qty' => 1, 'price' => 40, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 1, 'price' => 15, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -736,17 +774,18 @@ public function getProductConfiguration6($selectionsPriceType, $customOptionsPri ] ], [ + 'title' => 'Op2', + 'required' => true, 'type' => 'checkbox', 'links' => [ [ 'sku' => 'simple1', - 'option_id' => 2, + 'qty' => 1, 'price' => 20, 'price_type' => $selectionsPriceType ], [ 'sku' => 'simple2', - 'option_id' => 2, 'price' => 10, 'qty' => 3, 'price_type' => $selectionsPriceType @@ -757,11 +796,26 @@ public function getProductConfiguration6($selectionsPriceType, $customOptionsPri $customOptionsData = [ [ - 'price_type' => $customOptionsPriceType + 'price_type' => $customOptionsPriceType, + 'title' => 'Test Field', + 'type' => 'field', + 'is_require' => 1, + 'price' => 100, + 'sku' => '1-text', ] ]; + $tierPriceData = [ + 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, + 'qty' => 1, + 'value' => 50 + ]; + return [ + [ + 'modifierName' => 'addTierPrice', + 'data' => [$tierPriceData] + ], [ 'modifierName' => 'addSimpleProduct', 'data' => [$optionsData] @@ -773,94 +827,18 @@ public function getProductConfiguration6($selectionsPriceType, $customOptionsPri ]; } - private function getFixtureForProductOption(array $data = []) - { - $fixture = $this->fixtureForProductOption; - - // make title different for each call - $fixture['title'] .= ' ' . microtime(true); - - return array_merge($fixture, $data); - } - - private function getFixtureForProductOptionSelection($data) - { - $fixture = $this->fixtureForProductOptionSelection; - - return array_merge($fixture, $data); - } - - private function getFixtureForProductCustomOption(array $data = []) - { - $fixture = $this->fixtureForProductCustomOption; - - // make title and sku different for each call - $fixture['title'] .= ' ' . microtime(true); - $fixture['sku'] .= ' ' . microtime(true); - - return array_merge($fixture, $data); - } - - protected function addSimpleProduct(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) - { - $options = []; - - foreach ($optionsData as $optionData) { - $links = []; - $linksData = $optionData['links']; - unset($optionData['links']); - - $option = $this->objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOption($optionData)]) - ->setSku($bundleProduct->getSku()) - ->setOptionid(null); - - foreach ($linksData as $linkData) { - $links[] = $this->objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) - ->create(['data' => $this->getFixtureForProductOptionSelection($linkData)]); - } - - $option->setProductLinks($links); - $options[] = $option; - } - - $extension = $bundleProduct->getExtensionAttributes(); - $extension->setBundleProductOptions($options); - $bundleProduct->setExtensionAttributes($extension); - - return $bundleProduct; - } - - protected function addCustomOption(\Magento\Catalog\Model\Product $bundleProduct, array $optionsData) - { - /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */ - $customOptionFactory = $this->objectManager - ->create(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); - - $options = []; - foreach ($optionsData as $optionData) { - $customOption = $customOptionFactory->create( - [ - 'data' => $this->getFixtureForProductCustomOption($optionData) - ] - ); - $customOption->setProductSku($bundleProduct->getSku()); - $customOption->setOptionId(null); - - $options[] = $customOption; - } - - $bundleProduct->setOptions($options); - $bundleProduct->setCanSaveCustomOptions(true); - - return $bundleProduct; - } - - private function addTierPrice(\Magento\Catalog\Model\Product $bundleProduct) + /** + * @param \Magento\Catalog\Model\Product $product + * @param array $tirePriceData + * @return \Magento\Catalog\Model\Product + */ + protected function addTierPrice(\Magento\Catalog\Model\Product $product, $tirePriceData) { - $tierPrice = $this->tierPriceFactory->create($this->fixtureForTierPrice); - $bundleProduct->setTierPrices([$tierPrice]); + $tierPrice = $this->tierPriceFactory->create([ + 'data' => $tirePriceData + ]); + $product->setTierPrices([$tierPrice]); - return $bundleProduct; + return $product; } } From 000f93f0a215b4ec4564cea3c9027b4e814a1c9a Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Mon, 31 Oct 2016 11:13:17 +0200 Subject: [PATCH 035/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - FixedBundleTests refactoring --- .../Model/Product/FixedBundleWithTierPriceCalculatorTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php index d9e9359c59c43..949f3dc80b5e7 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php @@ -27,8 +27,8 @@ protected function setUp() } /** - * @param $strategyModifiers array - * @param $expectedResults array + * @param array $strategyModifiers + * @param array $expectedResults * @dataProvider getTestCases * @magentoAppIsolation enabled */ From 3a7632aab5ef76307c55d89d0b7a8a8eacf6436f Mon Sep 17 00:00:00 2001 From: Michail Slabko Date: Mon, 31 Oct 2016 17:05:35 +0200 Subject: [PATCH 036/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-56749: Optimize StoreFront performance --- .../Catalog/Product/View/Type/Bundle.php | 23 ++++++++++++++++++- .../Bundle/Pricing/Adjustment/Calculator.php | 22 +++++++++++++----- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php index 4a2df72c8f979..b413dde5c244c 100644 --- a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php +++ b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php @@ -48,6 +48,11 @@ class Bundle extends \Magento\Catalog\Block\Product\View\AbstractView */ private $selectedOptions = []; + /** + * @var \Magento\CatalogRule\Model\ResourceModel\Product\Collection + */ + private $catalogRuleProcessor; + /** * @param \Magento\Catalog\Block\Product\Context $context * @param \Magento\Framework\Stdlib\ArrayUtils $arrayUtils @@ -77,6 +82,20 @@ public function __construct( ); } + /** + * @deprecated + * @return \Magento\CatalogRule\Model\ResourceModel\Product\Collection + */ + private function getCatalogRuleProcessor() + { + if ($this->catalogRuleProcessor === null) { + $this->catalogRuleProcessor = \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\CatalogRule\Model\ResourceModel\Product\Collection::class); + } + + return $this->catalogRuleProcessor; + } + /** * Returns the bundle product options * Will return cached options data if the product options are already initialized @@ -95,10 +114,12 @@ public function getOptions($stripSelection = false) $optionCollection = $typeInstance->getOptionsCollection($product); - $selectionCollection = $typeInstance->getSelectionsCollection( + $selectionCollection = clone $typeInstance->getSelectionsCollection( $typeInstance->getOptionsIds($product), $product ); + $this->getCatalogRuleProcessor()->addPriceData($selectionCollection); + $selectionCollection->addTierPriceData(); $this->options = $optionCollection->appendSelections( $selectionCollection, diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php index 3a83a38ba6510..b466f4600632a 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php @@ -51,6 +51,11 @@ class Calculator implements BundleCalculatorInterface */ protected $priceCurrency; + /** + * @var \Magento\Framework\Pricing\Amount\AmountInterface[] + */ + private $optionAmount = []; + /** * @param CalculatorBase $calculator * @param AmountFactory $amountFactory @@ -143,12 +148,17 @@ public function getOptionsAmount( $baseAmount = 0., $useRegularPrice = false ) { - return $this->calculateBundleAmount( - $baseAmount, - $saleableItem, - $this->getSelectionAmounts($saleableItem, $searchMin, $useRegularPrice), - $exclude - ); + $cacheKey = implode('-', [$saleableItem->getId(), $exclude, $searchMin, $baseAmount, $useRegularPrice]); + if (!isset($this->optionAmount[$cacheKey])) { + $this->optionAmount[$cacheKey] = $this->calculateBundleAmount( + $baseAmount, + $saleableItem, + $this->getSelectionAmounts($saleableItem, $searchMin, $useRegularPrice), + $exclude + ); + } + + return $this->optionAmount[$cacheKey]; } /** From 1527713f82aa535692d23b3f5c432b80b13f89ae Mon Sep 17 00:00:00 2001 From: Vitaliy Goncharenko Date: Tue, 1 Nov 2016 11:36:32 +0200 Subject: [PATCH 037/161] MAGETWO-60283: Prices of configurable product are incorrectly recalculated when display currency is changed --- .../Magento/Catalog/Block/Product/View.php | 29 ++++------- .../Test/Repository/Product/CustomOptions.xml | 17 +++++++ .../Test/Repository/ConfigData.xml | 12 +++++ ...AssertCurrencyRateAppliedOnProductPage.php | 51 +++++++++++++++++++ .../Directory/Test/Repository/ConfigData.xml | 32 ++++++++++++ .../Test/TestCase/CreateCurrencyRateTest.php | 1 + .../Test/TestCase/CreateCurrencyRateTest.xml | 13 +++++ 7 files changed, 137 insertions(+), 18 deletions(-) create mode 100644 dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateAppliedOnProductPage.php create mode 100644 dev/tests/functional/tests/app/Magento/Directory/Test/Repository/ConfigData.xml diff --git a/app/code/Magento/Catalog/Block/Product/View.php b/app/code/Magento/Catalog/Block/Product/View.php index 8157ab4de07f2..b100ac3643dc1 100644 --- a/app/code/Magento/Catalog/Block/Product/View.php +++ b/app/code/Magento/Catalog/Block/Product/View.php @@ -7,7 +7,6 @@ use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\Category; -use Magento\Catalog\Model\Product; /** * Product View block @@ -225,40 +224,34 @@ public function getJsonConfig() $config = [ 'productId' => $product->getId(), 'priceFormat' => $this->_localeFormat->getPriceFormat() - ]; + ]; return $this->_jsonEncoder->encode($config); } $tierPrices = []; $tierPricesList = $product->getPriceInfo()->getPrice('tier_price')->getTierPriceList(); foreach ($tierPricesList as $tierPrice) { - $tierPrices[] = $this->priceCurrency->convert($tierPrice['price']->getValue()); + $tierPrices[] = $tierPrice['price']->getValue(); } $config = [ - 'productId' => $product->getId(), + 'productId' => $product->getId(), 'priceFormat' => $this->_localeFormat->getPriceFormat(), - 'prices' => [ - 'oldPrice' => [ - 'amount' => $this->priceCurrency->convert( - $product->getPriceInfo()->getPrice('regular_price')->getAmount()->getValue() - ), + 'prices' => [ + 'oldPrice' => [ + 'amount' => $product->getPriceInfo()->getPrice('regular_price')->getAmount()->getValue(), 'adjustments' => [] ], - 'basePrice' => [ - 'amount' => $this->priceCurrency->convert( - $product->getPriceInfo()->getPrice('final_price')->getAmount()->getBaseAmount() - ), + 'basePrice' => [ + 'amount' => $product->getPriceInfo()->getPrice('final_price')->getAmount()->getBaseAmount(), 'adjustments' => [] ], 'finalPrice' => [ - 'amount' => $this->priceCurrency->convert( - $product->getPriceInfo()->getPrice('final_price')->getAmount()->getValue() - ), + 'amount' => $product->getPriceInfo()->getPrice('final_price')->getAmount()->getValue(), 'adjustments' => [] ] ], - 'idSuffix' => '_clone', - 'tierPrices' => $tierPrices + 'idSuffix' => '_clone', + 'tierPrices' => $tierPrices ]; $responseObject = new \Magento\Framework\DataObject(); diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/CustomOptions.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/CustomOptions.xml index 3252f0178e241..09fda73b2a404 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/CustomOptions.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/CustomOptions.xml @@ -358,5 +358,22 @@ + + + + Test1 option %isolation% + No + Text/Field + + + 10 + Fixed + sku1_%isolation% + 45 + + + + + diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml index 9df42574840d6..3a099d79d370a 100644 --- a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml +++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml @@ -48,6 +48,18 @@ USD + + currency + US Dollar + 1 + USD + + + currency + US Dollar + 1 + USD + diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateAppliedOnProductPage.php b/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateAppliedOnProductPage.php new file mode 100644 index 0000000000000..aee8b2e53c6f4 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateAppliedOnProductPage.php @@ -0,0 +1,51 @@ +open($_ENV['app_frontend_url'] . $product->getUrlKey() . '.html'); + + \PHPUnit_Framework_Assert::assertEquals( + $basePrice, + $view->getViewBlock()->getPriceBlock()->getPrice(''), + 'Wrong price is displayed on Product page.' + ); + } + + /** + * Returns a string representation of successful assertion. + * + * @return string + */ + public function toString() + { + return "Currency rate has been applied correctly on Product page."; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Directory/Test/Repository/ConfigData.xml new file mode 100644 index 0000000000000..e1ae1dc1ebfb5 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/Repository/ConfigData.xml @@ -0,0 +1,32 @@ + + + + + + + currency + 1 + + UAH + + + + currency + US Dollar + 1 + USD + + + currency + Ukrainian Hryvnia + 1 + UAH + + + + diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.php b/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.php index bc40a2ab98f6d..07daaff5d366f 100644 --- a/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.php +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.php @@ -68,6 +68,7 @@ public function test(CurrencyRate $currencyRate, CatalogProductSimple $product, // Steps: $this->currencyIndexPage->open(); + $this->currencyIndexPage->getCurrencyRateForm()->clickImportButton(); $this->currencyIndexPage->getCurrencyRateForm()->fill($currencyRate); $this->currencyIndexPage->getFormPageActions()->save(); } diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml b/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml index dd42950c18a78..083bcd5e4b0f1 100644 --- a/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml @@ -20,5 +20,18 @@ + + USD + UAH + 2.000 + currency_symbols_uah + simple_10_dollar + not_required_text_option + config_base_currency_us_display_currency_uah + ₴20.00 + test_type:acceptance_test + + + From a25a24cc25d29b9b98bb4f3de53e0f5615b1feff Mon Sep 17 00:00:00 2001 From: Michail Slabko Date: Tue, 1 Nov 2016 14:35:49 +0200 Subject: [PATCH 038/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-60305: Broken page with Fixed bundle with website price scope --- .../ResourceModel/Selection/Collection.php | 43 +++++++++++++++---- .../DynamicBundlePriceCalculatorTest.php | 28 ++++++++++++ .../FixedBundlePriceCalculatorTest.php | 31 ++++++++++++- 3 files changed, 91 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php index 83a2664ec70f3..bf3974ab13aff 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php @@ -31,6 +31,13 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection */ private $catalogRuleProcessor; + /** + * Is website scope prices joined to collection + + * @var bool + */ + private $websiteScopePriceJoined = false; + /** * @inheritDoc */ @@ -54,7 +61,7 @@ public function __construct( \Magento\Customer\Model\Session $customerSession, \Magento\Framework\Stdlib\DateTime $dateTime, GroupManagementInterface $groupManagement, - \Magento\CatalogRule\Model\ResourceModel\Product\Collection $catalogRuleProcessor, + \Magento\CatalogRule\Model\ResourceModel\Product\Collection $catalogRuleProcessor = null, \Magento\Framework\DB\Adapter\AdapterInterface $connection = null ) { parent::__construct( @@ -153,6 +160,8 @@ public function joinPrices($websiteId) 'price_scope' => 'price.website_id' ] ); + $this->websiteScopePriceJoined = true; + return $this; } @@ -228,7 +237,7 @@ public function getNewEmptyItem() /** * Add filter by price * - * @param Product $product + * @param \Magento\Catalog\Model\Product $product * @param bool $searchMin * @param bool $useRegularPrice * @@ -241,7 +250,7 @@ public function addPriceFilter($product, $searchMin, $useRegularPrice = false) if ($useRegularPrice) { $minimalPriceExpression = 'minimal_price'; } else { - $this->catalogRuleProcessor->addPriceData($this, 'selection.product_id'); + $this->getCatalogRuleProcessor()->addPriceData($this, 'selection.product_id'); $minimalPriceExpression = 'LEAST(minimal_price, IFNULL(catalog_rule_price, 99999999))'; } $orderByValue = new \Zend_Db_Expr( @@ -252,7 +261,6 @@ public function addPriceFilter($product, $searchMin, $useRegularPrice = false) ); } else { $connection = $this->getConnection(); - $websiteId = $this->_storeManager->getStore()->getWebsiteId(); $priceType = $connection->getIfNullSql( 'price.selection_price_type', 'selection.selection_price_type' @@ -261,11 +269,14 @@ public function addPriceFilter($product, $searchMin, $useRegularPrice = false) 'price.selection_price_value', 'selection.selection_price_value' ); - $this->getSelect()->joinLeft( - ['price' => $this->getTable('catalog_product_bundle_selection_price')], - 'selection.selection_id = price.selection_id AND price.website_id = ' . (int)$websiteId, - [] - ); + if (!$this->websiteScopePriceJoined) { + $websiteId = $this->_storeManager->getStore()->getWebsiteId(); + $this->getSelect()->joinLeft( + ['price' => $this->getTable('catalog_product_bundle_selection_price')], + 'selection.selection_id = price.selection_id AND price.website_id = ' . (int)$websiteId, + [] + ); + } $price = $connection->getCheckSql( $priceType . ' = 1', (float) $product->getPrice() . ' * '. $priceValue . ' / 100', @@ -280,6 +291,20 @@ public function addPriceFilter($product, $searchMin, $useRegularPrice = false) return $this; } + /** + * @return \Magento\CatalogRule\Model\ResourceModel\Product\Collection + * @deprecated + */ + private function getCatalogRuleProcessor() + { + if (null === $this->catalogRuleProcessor) { + $this->catalogRuleProcessor = \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\CatalogRule\Model\ResourceModel\Product\Collection::class); + } + + return $this->catalogRuleProcessor; + } + /** * Clear collection data after clone */ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php index 81052bd2cef54..ba698a7cc73f2 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php @@ -39,6 +39,34 @@ public function testPriceForDynamicBundle(array $strategyModifiers, array $expec ); } + /** + * @param array $strategyModifiers + * @param array $expectedResults + * @dataProvider getTestCases + * @magentoAppIsolation enabled + * @magentoConfigFixture current_store catalog/price/scope 1 + */ + public function testPriceForDynamicBundleInWebsiteScope(array $strategyModifiers, array $expectedResults) + { + $bundleProduct = $this->prepareFixture($strategyModifiers); + + /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ + $priceInfo = $bundleProduct->getPriceInfo(); + $priceCode = \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE; + + $this->assertEquals( + $expectedResults['minimalPrice'], + $priceInfo->getPrice($priceCode)->getMinimalPrice()->getValue(), + 'Failed to check minimal price on product' + ); + + $this->assertEquals( + $expectedResults['maximalPrice'], + $priceInfo->getPrice($priceCode)->getMaximalPrice()->getValue(), + 'Failed to check maximal price on product' + ); + } + public function getTestCases() { return [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php index 63d8e3ba060f0..5ad26638dea3f 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php @@ -15,8 +15,8 @@ class FixedBundlePriceCalculatorTest extends BundlePriceAbstract { /** - * @param $strategyModifiers array - * @param $expectedResults array + * @param array $strategyModifiers + * @param array $expectedResults * @dataProvider getTestCases * @magentoAppIsolation enabled */ @@ -41,6 +41,33 @@ public function testPriceForFixedBundle(array $strategyModifiers, array $expecte ); } + /** + * @param array $strategyModifiers + * @param array $expectedResults + * @dataProvider getTestCases + * @magentoAppIsolation enabled + * @magentoConfigFixture current_store catalog/price/scope 1 + */ + public function testPriceForFixedBundleInWebsiteScope(array $strategyModifiers, array $expectedResults) + { + $bundleProduct = $this->prepareFixture($strategyModifiers); + + /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ + $priceInfo = $bundleProduct->getPriceInfo(); + $priceCode = \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE; + + $this->assertEquals( + $expectedResults['minimalPrice'], + $priceInfo->getPrice($priceCode)->getMinimalPrice()->getValue(), + 'Failed to check minimal price on product' + ); + + $this->assertEquals( + $expectedResults['maximalPrice'], + $priceInfo->getPrice($priceCode)->getMaximalPrice()->getValue(), + 'Failed to check maximal price on product' + ); + } public function getTestCases() { From 27ee68c6d361c4513f82e691b8d786bac27730d8 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Tue, 1 Nov 2016 16:10:09 +0200 Subject: [PATCH 039/161] MAGETWO-56073: [Performance] Unnecessary duplicating AJAX request on Shopping cart page --- .../view/frontend/web/js/model/new-customer-address.js | 8 ++++---- .../Checkout/view/frontend/web/js/view/shipping.js | 2 +- .../view/frontend/web/js/model/customer/address.js | 8 +++++++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js index 9a3685b212b43..c215b1989edbe 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js @@ -10,13 +10,13 @@ define([], function () { * Returns new address object */ return function (addressData) { - var identifier = Date.now(); - var regionId = null; + var identifier = Date.now(), + regionId; if (addressData.region && addressData.region.region_id) { regionId = addressData.region.region_id; } else if (addressData.country_id && addressData.country_id == window.checkoutConfig.defaultCountryId) { - regionId = window.checkoutConfig.defaultRegionId; + regionId = window.checkoutConfig.defaultRegionId || undefined; } return { @@ -25,7 +25,7 @@ define([], function () { regionId: regionId || addressData.regionId, regionCode: (addressData.region) ? addressData.region.region_code : null, region: (addressData.region) ? addressData.region.region : null, - customerId: addressData.customer_id, + customerId: addressData.customer_id || addressData.customerId, street: addressData.street, company: addressData.company, telephone: addressData.telephone, diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js index 8910e41731d11..fb15e47eaf7d4 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js @@ -79,7 +79,6 @@ define( fieldsetName = 'checkout.steps.shipping-step.shippingAddress.shipping-address-fieldset'; this._super(); - shippingRatesValidator.initFields(fieldsetName); if (!quote.isVirtual()) { stepNavigator.registerStep( @@ -120,6 +119,7 @@ define( checkoutProvider.on('shippingAddress', function (shippingAddressData) { checkoutData.setShippingAddressFromData(shippingAddressData); }); + shippingRatesValidator.initFields(fieldsetName); }); return this; diff --git a/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js b/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js index 30fbef98fd39a..e013a96e4890a 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js +++ b/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js @@ -10,11 +10,17 @@ define([], function() { * Returns new address object */ return function (addressData) { + var regionId; + + if (addressData.region['region_id'] && addressData.region['region_id'] !== '0') { + regionId = addressData.region['region_id'] + ''; + } + return { customerAddressId: addressData.id, email: addressData.email, countryId: addressData.country_id, - regionId: addressData.region_id, + regionId: regionId, regionCode: addressData.region.region_code, region: addressData.region.region, customerId: addressData.customer_id, From 6a5ece2f27934b2ddf7a939617c12507d264ee90 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Wed, 2 Nov 2016 08:50:16 +0200 Subject: [PATCH 040/161] MAGETWO-59685: Checkout pages very slow due to pulling in JSON config, js scripts for unused payment & shipping methods #6997 #4868 --- .../Checkout/Block/Cart/LayoutProcessor.php | 11 +- .../Block/Checkout/AttributeMerger.php | 14 +- .../Block/Checkout/DirectoryDataProcessor.php | 146 ++++++++++++++++++ .../Block/Checkout/LayoutProcessor.php | 74 +++++++++ .../Unit/Block/Cart/LayoutProcessorTest.php | 9 +- .../Checkout/DirectoryDataProcessorTest.php | 114 ++++++++++++++ .../Block/Checkout/LayoutProcessorTest.php | 10 ++ app/code/Magento/Checkout/etc/frontend/di.xml | 1 + .../Model/ResourceModel/Region/Collection.php | 47 ++++++ .../ResourceModel/Region/CollectionTest.php | 34 +++- .../view/base/web/js/form/element/select.js | 46 ++---- .../Ui/base/js/form/element/select.test.js | 2 +- 12 files changed, 470 insertions(+), 38 deletions(-) create mode 100644 app/code/Magento/Checkout/Block/Checkout/DirectoryDataProcessor.php create mode 100644 app/code/Magento/Checkout/Test/Unit/Block/Checkout/DirectoryDataProcessorTest.php diff --git a/app/code/Magento/Checkout/Block/Cart/LayoutProcessor.php b/app/code/Magento/Checkout/Block/Cart/LayoutProcessor.php index a492002b0a5a5..a042c41634bcb 100644 --- a/app/code/Magento/Checkout/Block/Cart/LayoutProcessor.php +++ b/app/code/Magento/Checkout/Block/Cart/LayoutProcessor.php @@ -85,14 +85,14 @@ public function process($jsLayout) 'visible' => true, 'formElement' => 'select', 'label' => __('Country'), - 'options' => $this->countryCollection->loadByStore()->toOptionArray(), + 'options' => [], 'value' => null ], 'region_id' => [ 'visible' => true, 'formElement' => 'select', 'label' => __('State/Province'), - 'options' => $this->regionCollection->load()->toOptionArray(), + 'options' => [], 'value' => null ], 'postcode' => [ @@ -103,6 +103,13 @@ public function process($jsLayout) ] ]; + if (!isset($jsLayout['components']['checkoutProvider']['dictionaries'])) { + $jsLayout['components']['checkoutProvider']['dictionaries'] = [ + 'country_id' => $this->countryCollection->loadByStore()->toOptionArray(), + 'region_id' => $this->regionCollection->addAllowedCountriesFilter()->toOptionArray(), + ]; + } + if (isset($jsLayout['components']['block-summary']['children']['block-shipping']['children'] ['address-fieldsets']['children']) ) { diff --git a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php index 1882d88e04a8b..e7686e4bea58b 100644 --- a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php +++ b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php @@ -192,6 +192,15 @@ protected function getFieldConfig( 'visible' => isset($additionalConfig['visible']) ? $additionalConfig['visible'] : true, ]; + if ($attributeCode === 'region_id' || $attributeCode === 'country_id') { + unset($element['options']); + $element['deps'] = [$providerName]; + $element['imports'] = [ + 'initialOptions' => 'index = ' . $providerName . ':dictionaries.' . $attributeCode, + 'setOptions' => 'index = ' . $providerName . ':dictionaries.' . $attributeCode + ]; + } + if (isset($attributeConfig['value']) && $attributeConfig['value'] != null) { $element['value'] = $attributeConfig['value']; } elseif (isset($attributeConfig['default']) && $attributeConfig['default'] != null) { @@ -341,11 +350,11 @@ protected function getCustomer() * @param string $attributeCode * @param array $attributeConfig * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ protected function getFieldOptions($attributeCode, array $attributeConfig) { - $options = isset($attributeConfig['options']) ? $attributeConfig['options'] : []; - return ($attributeCode == 'country_id') ? $this->orderCountryOptions($options) : $options; + return isset($attributeConfig['options']) ? $attributeConfig['options'] : []; } /** @@ -353,6 +362,7 @@ protected function getFieldOptions($attributeCode, array $attributeConfig) * * @param array $countryOptions * @return array + * @deprecated */ protected function orderCountryOptions(array $countryOptions) { diff --git a/app/code/Magento/Checkout/Block/Checkout/DirectoryDataProcessor.php b/app/code/Magento/Checkout/Block/Checkout/DirectoryDataProcessor.php new file mode 100644 index 0000000000000..4a02ebbd079a4 --- /dev/null +++ b/app/code/Magento/Checkout/Block/Checkout/DirectoryDataProcessor.php @@ -0,0 +1,146 @@ +countryCollectionFactory = $countryCollection; + $this->regionCollectionFactory = $regionCollection; + $this->storeResolver = $storeResolver; + $this->directoryHelper = $directoryHelper; + } + + /** + * Process js Layout of block + * + * @param array $jsLayout + * @return array + */ + public function process($jsLayout) + { + if (!isset($jsLayout['components']['checkoutProvider']['dictionaries'])) { + $jsLayout['components']['checkoutProvider']['dictionaries'] = [ + 'country_id' => $this->getCountryOptions(), + 'region_id' => $this->getRegionOptions(), + ]; + } + + return $jsLayout; + } + + /** + * Get country options list. + * + * @return array + */ + private function getCountryOptions() + { + if (!isset($this->countryOptions)) { + $this->countryOptions = $this->countryCollectionFactory->create()->loadByStore( + $this->storeResolver->getCurrentStoreId() + )->toOptionArray(); + $this->countryOptions = $this->orderCountryOptions($this->countryOptions); + } + + return $this->countryOptions; + } + + /** + * Get region options list. + * + * @return array + */ + private function getRegionOptions() + { + if (!isset($this->regionOptions)) { + $this->regionOptions = $this->regionCollectionFactory->create()->addAllowedCountriesFilter( + $this->storeResolver->getCurrentStoreId() + )->toOptionArray(); + } + + return $this->regionOptions; + } + + /** + * Sort country options by top country codes. + * + * @param array $countryOptions + * @return array + */ + private function orderCountryOptions(array $countryOptions) + { + $topCountryCodes = $this->directoryHelper->getTopCountryCodes(); + if (empty($topCountryCodes)) { + return $countryOptions; + } + + $headOptions = []; + $tailOptions = [[ + 'value' => 'delimiter', + 'label' => '──────────', + 'disabled' => true, + ]]; + foreach ($countryOptions as $countryOption) { + if (empty($countryOption['value']) || in_array($countryOption['value'], $topCountryCodes)) { + array_push($headOptions, $countryOption); + } else { + array_push($tailOptions, $countryOption); + } + } + return array_merge($headOptions, $tailOptions); + } +} diff --git a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php index 1b2c744419891..f7472aadaf765 100644 --- a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php +++ b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php @@ -7,7 +7,11 @@ use Magento\Checkout\Helper\Data; use Magento\Framework\App\ObjectManager; +use Magento\Store\Api\StoreResolverInterface; +/** + * Class LayoutProcessor + */ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcessorInterface { /** @@ -35,6 +39,16 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso */ private $checkoutDataHelper; + /** + * @var StoreResolverInterface + */ + private $storeResolver; + + /** + * @var \Magento\Shipping\Model\Config + */ + private $shippingConfig; + /** * @param \Magento\Customer\Model\AttributeMetadataDataProvider $attributeMetadataDataProvider * @param \Magento\Ui\Component\Form\AttributeMapper $attributeMapper @@ -146,6 +160,16 @@ public function process($jsLayout) $elements ); } + if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children'] + ['step-config']['children']['shipping-rates-validation']['children'] + )) { + $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children'] + ['step-config']['children']['shipping-rates-validation']['children'] = + $this->processShippingChildrenComponents( + $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children'] + ['step-config']['children']['shipping-rates-validation']['children'] + ); + } if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step'] ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'] @@ -163,6 +187,26 @@ public function process($jsLayout) return $jsLayout; } + /** + * Process shipping configuration to exclude inactive carriers. + * + * @param array $shippingRatesLayout + * @return array + */ + private function processShippingChildrenComponents($shippingRatesLayout) + { + $activeCarriers = $this->getShippingConfig()->getActiveCarriers( + $this->getStoreResolver()->getCurrentStoreId() + ); + foreach (array_keys($shippingRatesLayout) as $carrierName) { + $carrierKey = str_replace('-rates-validation', '', $carrierName); + if (!array_key_exists($carrierKey, $activeCarriers)) { + unset($shippingRatesLayout[$carrierName]); + } + } + return $shippingRatesLayout; + } + /** * Appends billing address form component to payment layout * @param array $paymentLayout @@ -314,4 +358,34 @@ private function getCheckoutDataHelper() return $this->checkoutDataHelper; } + + /** + * Get active carriers list. + * + * @return array + * @deprecated + */ + private function getShippingConfig() + { + if (!$this->shippingConfig) { + $this->shippingConfig = ObjectManager::getInstance()->get(\Magento\Shipping\Model\Config::class); + } + + return $this->shippingConfig; + } + + /** + * Get store resolver. + * + * @return StoreResolverInterface + * @deprecated + */ + private function getStoreResolver() + { + if (!$this->storeResolver) { + $this->storeResolver = ObjectManager::getInstance()->get(StoreResolverInterface::class); + } + + return $this->storeResolver; + } } diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Cart/LayoutProcessorTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Cart/LayoutProcessorTest.php index 95ffed86cbb35..5eabb6c9c86a4 100644 --- a/app/code/Magento/Checkout/Test/Unit/Block/Cart/LayoutProcessorTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Block/Cart/LayoutProcessorTest.php @@ -69,7 +69,7 @@ public function testProcess() $this->countryCollection->expects($this->once())->method('loadByStore')->willReturnSelf(); $this->countryCollection->expects($this->once())->method('toOptionArray')->willReturn($countries); - $this->regionCollection->expects($this->once())->method('load')->willReturnSelf(); + $this->regionCollection->expects($this->once())->method('addAllowedCountriesFilter')->willReturnSelf(); $this->regionCollection->expects($this->once())->method('toOptionArray')->willReturn($regions); $layoutMerged = $layout; @@ -77,7 +77,12 @@ public function testProcess() ['address-fieldsets']['children']['fieldThree'] = ['param' => 'value']; $layoutMergedPointer = &$layoutMerged['components']['block-summary']['children']['block-shipping'] ['children']['address-fieldsets']['children']; - + $layoutMerged['components']['checkoutProvider'] = [ + 'dictionaries' => [ + 'country_id' => [], + 'region_id' => [], + ] + ]; $elements = [ 'city' => [ 'visible' => false, diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Checkout/DirectoryDataProcessorTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/DirectoryDataProcessorTest.php new file mode 100644 index 0000000000000..c84fac464c047 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/DirectoryDataProcessorTest.php @@ -0,0 +1,114 @@ +countryCollectionFactoryMock = $this->getMock( + \Magento\Directory\Model\ResourceModel\Country\CollectionFactory::class, + ['create'], + [], + '', + false + ); + $this->countryCollectionMock = $this->getMock( + \Magento\Directory\Model\ResourceModel\Country\Collection::class, + [], + [], + '', + false + ); + $this->regionCollectionFactoryMock = $this->getMock( + \Magento\Directory\Model\ResourceModel\Region\CollectionFactory::class, + ['create'], + [], + '', + false + ); + $this->regionCollectionMock = $this->getMock( + \Magento\Directory\Model\ResourceModel\Region\Collection::class, + [], + [], + '', + false + ); + $this->storeResolverMock = $this->getMock( + \Magento\Store\Api\StoreResolverInterface::class + ); + $this->directoryDataHelperMock = $this->getMock( + \Magento\Directory\Helper\Data::class, + [], + [], + '', + false + ); + + $this->model = new \Magento\Checkout\Block\Checkout\DirectoryDataProcessor( + $this->countryCollectionFactoryMock, + $this->regionCollectionFactoryMock, + $this->storeResolverMock, + $this->directoryDataHelperMock + ); + } + + public function testProcess() + { + $expectedResult['components']['checkoutProvider']['dictionaries'] = [ + 'country_id' => [], + 'region_id' => [], + ]; + + $this->countryCollectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->countryCollectionMock); + $this->countryCollectionMock->expects($this->once())->method('loadByStore')->willReturnSelf(); + $this->countryCollectionMock->expects($this->once())->method('toOptionArray')->willReturn([]); + $this->regionCollectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->regionCollectionMock); + $this->regionCollectionMock->expects($this->once())->method('addAllowedCountriesFilter')->willReturnSelf(); + $this->regionCollectionMock->expects($this->once())->method('toOptionArray')->willReturn([]); + + $this->assertEquals($expectedResult, $this->model->process([])); + } +} diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php index 1351213f990b5..95aed9b56afc3 100644 --- a/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php @@ -17,6 +17,8 @@ /** * LayoutProcessorTest covers a list of variations for * checkout layout processor + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class LayoutProcessorTest extends \PHPUnit_Framework_TestCase { @@ -45,6 +47,11 @@ class LayoutProcessorTest extends \PHPUnit_Framework_TestCase */ private $layoutProcessor; + /** + * @var MockObject + */ + private $storeResolver; + protected function setUp() { $objectManager = new ObjectManager($this); @@ -79,8 +86,11 @@ protected function setUp() $this->attributeMerger ); + $this->storeResolver = $this->getMock(\Magento\Store\Api\StoreResolverInterface::class); + $objectManager->setBackwardCompatibleProperty($this->layoutProcessor, 'checkoutDataHelper', $this->dataHelper); $objectManager->setBackwardCompatibleProperty($this->layoutProcessor, 'options', $options); + $objectManager->setBackwardCompatibleProperty($this->layoutProcessor, 'storeResolver', $this->storeResolver); } /** diff --git a/app/code/Magento/Checkout/etc/frontend/di.xml b/app/code/Magento/Checkout/etc/frontend/di.xml index 6fb9058c3b768..69ed33721740d 100644 --- a/app/code/Magento/Checkout/etc/frontend/di.xml +++ b/app/code/Magento/Checkout/etc/frontend/di.xml @@ -55,6 +55,7 @@ Magento\Checkout\Block\Checkout\LayoutProcessor Magento\Checkout\Block\Checkout\TotalsProcessor + Magento\Checkout\Block\Checkout\DirectoryDataProcessor diff --git a/app/code/Magento/Directory/Model/ResourceModel/Region/Collection.php b/app/code/Magento/Directory/Model/ResourceModel/Region/Collection.php index 718e0c0223d76..3fdb20165d4be 100644 --- a/app/code/Magento/Directory/Model/ResourceModel/Region/Collection.php +++ b/app/code/Magento/Directory/Model/ResourceModel/Region/Collection.php @@ -9,6 +9,14 @@ */ namespace Magento\Directory\Model\ResourceModel\Region; +use Magento\Directory\Model\AllowedCountries; +use Magento\Framework\App\ObjectManager; +use Magento\Store\Model\ScopeInterface; + +/** + * Class Collection + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection { /** @@ -30,6 +38,11 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab */ protected $_localeResolver; + /** + * @var AllowedCountries + */ + private $allowedCountriesReader; + /** * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory * @param \Psr\Log\LoggerInterface $logger @@ -89,6 +102,40 @@ protected function _initSelect() return $this; } + /** + * Return Allowed Countries reader + * + * @return \Magento\Directory\Model\AllowedCountries + * @deprecated + */ + private function getAllowedCountriesReader() + { + if (!$this->allowedCountriesReader) { + $this->allowedCountriesReader = ObjectManager::getInstance()->get(AllowedCountries::class); + } + + return $this->allowedCountriesReader; + } + + /** + * Set allowed countries filter based on the given store. + * This is a convenience method for collection filtering based on store configuration settings. + * + * @param null|int|string|\Magento\Store\Model\Store $store + * @return \Magento\Directory\Model\ResourceModel\Region\Collection + */ + public function addAllowedCountriesFilter($store = null) + { + $allowedCountries = $this->getAllowedCountriesReader() + ->getAllowedCountries(ScopeInterface::SCOPE_STORE, $store); + + if (!empty($allowedCountries)) { + $this->addFieldToFilter('main_table.country_id', ['in' => $allowedCountries]); + } + + return $this; + } + /** * Filter by country_id * diff --git a/app/code/Magento/Directory/Test/Unit/Model/ResourceModel/Region/CollectionTest.php b/app/code/Magento/Directory/Test/Unit/Model/ResourceModel/Region/CollectionTest.php index 59c054b00a5f9..5c09ab119295a 100644 --- a/app/code/Magento/Directory/Test/Unit/Model/ResourceModel/Region/CollectionTest.php +++ b/app/code/Magento/Directory/Test/Unit/Model/ResourceModel/Region/CollectionTest.php @@ -6,6 +6,7 @@ namespace Magento\Directory\Test\Unit\Model\ResourceModel\Region; use Magento\Directory\Model\ResourceModel\Region\Collection; +use Magento\Directory\Model\AllowedCountries; use Magento\Framework\DB\Adapter\Pdo\Mysql; use Magento\Framework\DB\Select; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; @@ -15,7 +16,14 @@ use Magento\Framework\Locale\ResolverInterface; use Magento\Framework\DataObject; use Psr\Log\LoggerInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit_Framework_MockObject_MockObject as MockObject; +/** + * Class CollectionTest + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class CollectionTest extends \PHPUnit_Framework_TestCase { /** @@ -23,15 +31,22 @@ class CollectionTest extends \PHPUnit_Framework_TestCase */ private $collection; + /** + * @var MockObject + */ + private $allowedCountries; + protected function setUp() { + $objectManager = new ObjectManager($this); $entityFactoryMock = $this->getMock(EntityFactory::class, [], [], '', false); $loggerMock = $this->getMock(LoggerInterface::class); $fetchStrategyMock = $this->getMock(FetchStrategyInterface::class); $eventManagerMock = $this->getMock(ManagerInterface::class); $localeResolverMock = $this->getMock(ResolverInterface::class); $connectionMock = $this->getMock(Mysql::class, [], [], '', false); - $resourceMock = $this->getMockForAbstractClass(AbstractDb::class, + $resourceMock = $this->getMockForAbstractClass( + AbstractDb::class, [], '', false, @@ -39,6 +54,7 @@ protected function setUp() true, ['getConnection', 'getMainTable', 'getTable', '__wakeup'] ); + $this->allowedCountries = $this->getMock(AllowedCountries::class, [], [], '', false); $selectMock = $this->getMock(Select::class, [], [], '', false); $connectionMock->expects($this->any())->method('select')->will($this->returnValue($selectMock)); @@ -54,6 +70,12 @@ protected function setUp() $connectionMock, $resourceMock ); + + $objectManager->setBackwardCompatibleProperty( + $this->collection, + 'allowedCountriesReader', + $this->allowedCountries + ); } public function testToOptionArray() @@ -98,4 +120,14 @@ public function testToOptionArray() $this->assertEquals($expectedResult, $this->collection->toOptionArray()); } + + public function testAddAllowedCountriesFilter() + { + $allowedCountries = [1, 2, 3]; + $this->allowedCountries->expects($this->once())->method('getAllowedCountries')->with( + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + null + )->willReturn($allowedCountries); + $this->assertEquals($this->collection->addAllowedCountriesFilter(), $this->collection); + } } diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/select.js b/app/code/Magento/Ui/view/base/web/js/form/element/select.js index 1887639c8d031..4567bba1d017a 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/select.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/select.js @@ -105,7 +105,9 @@ define([ return Abstract.extend({ defaults: { customName: '${ $.parentName }.${ $.index }_input', - elementTmpl: 'ui/form/element/select' + elementTmpl: 'ui/form/element/select', + caption: '', + options: [] }, /** @@ -127,28 +129,6 @@ define([ return this; }, - /** - * Parses options and merges the result with instance - * - * @param {Object} config - * @returns {Object} Chainable. - */ - initConfig: function (config) { - var options = config.options, - captionValue = config.captionValue || '', - result = parseOptions(options, captionValue); - - if (config.caption) { - delete result.caption; - } - - _.extend(config, result); - - this._super(); - - return this; - }, - /** * Calls 'initObservable' of parent, initializes 'options' and 'initialOptions' * properties, calls 'setOptions' passing options to it @@ -160,7 +140,7 @@ define([ this.initialOptions = this.options; - this.observe('options') + this.observe('options caption') .setOptions(this.options()); return this; @@ -209,7 +189,7 @@ define([ return option && option.value; } - if (!this.caption) { + if (!this.caption()) { return findFirst(this.options); } }, @@ -254,14 +234,20 @@ define([ * @returns {Object} Chainable */ setOptions: function (data) { - var isVisible; + var captionValue = this.captionValue || '', + result = parseOptions(data, captionValue), + isVisible; + + this.indexedOptions = indexOptions(result.options); - this.indexedOptions = indexOptions(data); + this.options(result.options); - this.options(data); + if (!this.caption()) { + this.caption(result.caption); + } if (this.customEntry) { - isVisible = !!data.length; + isVisible = !!result.options.length; this.setVisible(isVisible); this.toggleInput(!isVisible); @@ -301,7 +287,7 @@ define([ * @returns {Object} Chainable. */ clear: function () { - var value = this.caption ? '' : findFirst(this.options); + var value = this.caption() ? '' : findFirst(this.options); this.value(value); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js index db5855b0a692b..5d75b8c595366 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js @@ -121,7 +121,7 @@ define([ { value: 'valLast' }]; - model.caption = false; + model.caption(''); expect(model.normalizeData('')).toEqual('valFirst'); }); }); From 93af2417b24a1c12629022e9e7944375223e81e2 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Wed, 2 Nov 2016 08:51:34 +0200 Subject: [PATCH 041/161] MAGETWO-60110: [Github] Shipping Estimation Address is Merged with Customer Default Address during Checkout #6869 --- .../view/frontend/web/js/view/cart/shipping-estimation.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js index 3d4612fbe9ec5..cd43dc646584d 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js @@ -52,9 +52,9 @@ define( addressConverter.quoteAddressToFormAddressData(address) : { // only the following fields must be used by estimation form data provider - country_id: address.countryId, + 'country_id': address.countryId, region: address.region, - region_id: address.regionId, + 'region_id': address.regionId, postcode: address.postcode }; checkoutProvider.set( From 5da49c002963ef5c5e37b522815883acfe79a00c Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Wed, 2 Nov 2016 09:46:15 +0200 Subject: [PATCH 042/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - refactoring for static tests --- .../ResourceModel/Selection/Collection.php | 3 +- .../Model/Product/BundlePriceAbstract.php | 19 +++-- .../DynamicBundlePriceCalculatorTest.php | 22 +++-- ...ndleWithCatalogPriceRuleCalculatorTest.php | 43 +++++----- ...icBundleWithSpecialPriceCalculatorTest.php | 47 +++++----- ...namicBundleWithTierPriceCalculatorTest.php | 47 +++++----- .../FixedBundlePriceCalculatorTest.php | 26 +++--- ...ndleWithCatalogPriceRuleCalculatorTest.php | 81 +++++++++--------- ...edBundleWithSpecialPriceCalculatorTest.php | 85 ++++++++++--------- ...FixedBundleWithTierPriceCalculatorTest.php | 71 ++++++++-------- .../Bundle/Model/Product/IsSaleableTest.php | 42 ++++++--- .../dynamic_bundle_product.php | 4 +- .../dynamic_bundle_product_rollback.php | 2 +- .../PriceCalculator/fixed_bundle_product.php | 4 +- .../fixed_bundle_product_rollback.php | 2 +- .../Bundle/_files/issaleable_product.php | 2 +- .../_files/issaleable_product_rollback.php | 3 +- .../Bundle/_files/multiple_products.php | 5 +- 18 files changed, 285 insertions(+), 223 deletions(-) diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php index bf3974ab13aff..afb04e62bf467 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php @@ -33,7 +33,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection /** * Is website scope prices joined to collection - + * * @var bool */ private $websiteScopePriceJoined = false; @@ -307,6 +307,7 @@ private function getCatalogRuleProcessor() /** * Clear collection data after clone + * @return void */ public function __clone() { diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePriceAbstract.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePriceAbstract.php index b71a40cbdb561..86bc9f2c80744 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePriceAbstract.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePriceAbstract.php @@ -5,6 +5,7 @@ */ namespace Magento\Bundle\Model\Product; + use Zend\Console\Exception\InvalidArgumentException; /** @@ -12,8 +13,10 @@ */ abstract class BundlePriceAbstract extends \PHPUnit_Framework_TestCase { + /** Fixed price type for product custom option */ const CUSTOM_OPTION_PRICE_TYPE_FIXED = 'fixed'; + /** Percent price type for product custom option */ const CUSTOM_OPTION_PRICE_TYPE_PERCENT = 'percent'; /** @var \Magento\TestFramework\Helper\Bootstrap */ @@ -35,13 +38,18 @@ protected function setUp() abstract public function getTestCases(); /** - * @param $strategyModifiers - * @throws InvalidArgumentException + * @param array $strategyModifiers + * @param string $productSku * @return \Magento\Catalog\Api\Data\ProductInterface + * @throws InvalidArgumentException + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\StateException + * @throws \Magento\Framework\Exception\CouldNotSaveException */ - protected function prepareFixture($strategyModifiers) + protected function prepareFixture($strategyModifiers, $productSku) { - $bundleProduct = $this->productRepository->get('spherical_horse_in_a_vacuum'); + $bundleProduct = $this->productRepository->get($productSku); foreach ($strategyModifiers as $modifier) { if (method_exists($this, $modifier['modifierName'])) { @@ -54,8 +62,7 @@ protected function prepareFixture($strategyModifiers) } } - $this->productRepository->save($bundleProduct); - return $this->productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + return $this->productRepository->save($bundleProduct); } /** diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php index ba698a7cc73f2..3cc9939ba38ad 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php @@ -20,7 +20,8 @@ class DynamicBundlePriceCalculatorTest extends BundlePriceAbstract */ public function testPriceForDynamicBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->prepareFixture($strategyModifiers); + $this->prepareFixture($strategyModifiers, 'bundle_product'); + $bundleProduct = $this->productRepository->get('bundle_product', false, null, true); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -48,7 +49,8 @@ public function testPriceForDynamicBundle(array $strategyModifiers, array $expec */ public function testPriceForDynamicBundleInWebsiteScope(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->prepareFixture($strategyModifiers); + $this->prepareFixture($strategyModifiers, 'bundle_product'); + $bundleProduct = $this->productRepository->get('bundle_product', false, null, true); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -67,10 +69,14 @@ public function testPriceForDynamicBundleInWebsiteScope(array $strategyModifiers ); } + /** + * Test cases for current test + * @return array + */ public function getTestCases() { return [ - 'Testing price for dynamic bundle product with one simple' => [ + '#1 Testing price for dynamic bundle product with one simple' => [ 'strategy' => $this->getProductWithOneSimple(), 'expectedResults' => [ // just price from simple1 @@ -79,7 +85,7 @@ public function getTestCases() 'maximalPrice' => 10 ] ], - 'Testing price for dynamic bundle product with three simples and different qty' => [ + '#2 Testing price for dynamic bundle product with three simples and different qty' => [ 'strategy' => $this->getProductWithDifferentQty(), 'expectedResults' => [ // min price from simples 3*10 or 30 @@ -88,7 +94,7 @@ public function getTestCases() 'maximalPrice' => 100 ] ], - 'Testing price for dynamic bundle product with four simples and different price' => [ + '#3 Testing price for dynamic bundle product with four simples and different price' => [ 'strategy' => $this->getProductWithDifferentPrice(), 'expectedResults' => [ // 10 @@ -100,7 +106,7 @@ public function getTestCases() ]; } - public function getProductWithOneSimple() + private function getProductWithOneSimple() { $optionsData = [ [ @@ -124,7 +130,7 @@ public function getProductWithOneSimple() ]; } - public function getProductWithDifferentQty() + private function getProductWithDifferentQty() { $optionsData = [ [ @@ -156,7 +162,7 @@ public function getProductWithDifferentQty() ]; } - public function getProductWithDifferentPrice() + private function getProductWithDifferentPrice() { $optionsData = [ [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php index fd6554b3b1d08..41644729fece3 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php @@ -20,7 +20,8 @@ class DynamicBundleWithCatalogPriceRuleCalculatorTest extends BundlePriceAbstrac */ public function testPriceForDynamicBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->prepareFixture($strategyModifiers); + $this->prepareFixture($strategyModifiers, 'bundle_product'); + $bundleProduct = $this->productRepository->get('bundle_product', false, null, true); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -39,10 +40,14 @@ public function testPriceForDynamicBundle(array $strategyModifiers, array $expec ); } + /** + * Test cases for current test + * @return array + */ public function getTestCases() { return [ - 'Testing price for dynamic bundle product with sub items and catalog rule price' => [ + '#1 Testing price for dynamic bundle product with sub items and catalog rule price' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy(), 'expectedResults' => [ // 10 * 0.9 @@ -53,7 +58,7 @@ public function getTestCases() ] ], - 'Testing price for dynamic bundle product with special price, sub items and catalog rule price' => [ + '#2 Testing price for dynamic bundle product with special price, sub items and catalog rule price' => [ 'strategy' => $this->getBundleProductConfiguration1(), 'expectedResults' => [ // 0.5 * 10 * 0.9 @@ -64,7 +69,7 @@ public function getTestCases() ] ], - 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #2' => [ + '#3 Testing price for dynamic bundle product with sub items and catalog rule price Configuration #2' => [ 'strategy' => $this->getBundleProductConfiguration2(), 'expectedResults' => [ // 0.9 * 2 * 10 @@ -75,7 +80,7 @@ public function getTestCases() ] ], - 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #3' => [ + '#4 Testing price for dynamic bundle product with sub items and catalog rule price Configuration #3' => [ 'strategy' => $this->getBundleProductConfiguration3(), 'expectedResults' => [ // 0.9 * 1 * 10 @@ -86,7 +91,7 @@ public function getTestCases() ] ], - 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #4' => [ + '#5 Testing price for dynamic bundle product with sub items and catalog rule price Configuration #4' => [ 'strategy' => $this->getBundleProductConfiguration4(), 'expectedResults' => [ // 0.9 * 1 * 10 @@ -97,7 +102,7 @@ public function getTestCases() ] ], - 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #5' => [ + '#6 Testing price for dynamic bundle product with sub items and catalog rule price Configuration #5' => [ 'strategy' => $this->getBundleProductConfiguration5(), 'expectedResults' => [ // 0.9 * 1 * 10 @@ -108,7 +113,7 @@ public function getTestCases() ] ], - 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #6' => [ + '#7 Testing price for dynamic bundle product with sub items and catalog rule price Configuration #6' => [ 'strategy' => $this->getBundleProductConfiguration6(), 'expectedResults' => [ // 0.9 * 1 * 10 + 0.9 * 1 * 10 @@ -119,7 +124,7 @@ public function getTestCases() ] ], - 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #7' => [ + '#8 Testing price for dynamic bundle product with sub items and catalog rule price Configuration #7' => [ 'strategy' => $this->getBundleProductConfiguration7(), 'expectedResults' => [ // 1 * 0.9 * 10 @@ -130,7 +135,7 @@ public function getTestCases() ] ], - 'Testing price for dynamic bundle product with sub items and catalog rule price Configuration #8' => [ + '#9 Testing price for dynamic bundle product with sub items and catalog rule price Configuration #8' => [ 'strategy' => $this->getBundleProductConfiguration8(), 'expectedResults' => [ // 0.9 * 1 * 10 @@ -143,7 +148,7 @@ public function getTestCases() ]; } - public function getProductWithSubItemsAndOptionsStrategy() + private function getProductWithSubItemsAndOptionsStrategy() { $optionsData = [ [ @@ -167,7 +172,7 @@ public function getProductWithSubItemsAndOptionsStrategy() ]; } - public function getBundleProductConfiguration1() + private function getBundleProductConfiguration1() { $optionsData = [ [ @@ -195,7 +200,7 @@ public function getBundleProductConfiguration1() ]; } - public function getBundleProductConfiguration2() + private function getBundleProductConfiguration2() { $optionsData = [ [ @@ -219,7 +224,7 @@ public function getBundleProductConfiguration2() ]; } - public function getBundleProductConfiguration3() + private function getBundleProductConfiguration3() { $optionsData = [ [ @@ -247,7 +252,7 @@ public function getBundleProductConfiguration3() ]; } - public function getBundleProductConfiguration4() + private function getBundleProductConfiguration4() { $optionsData = [ [ @@ -275,7 +280,7 @@ public function getBundleProductConfiguration4() ]; } - public function getBundleProductConfiguration5() + private function getBundleProductConfiguration5() { $optionsData = [ [ @@ -303,7 +308,7 @@ public function getBundleProductConfiguration5() ]; } - public function getBundleProductConfiguration6() + private function getBundleProductConfiguration6() { $optionsData = [ [ @@ -346,7 +351,7 @@ public function getBundleProductConfiguration6() ]; } - public function getBundleProductConfiguration7() + private function getBundleProductConfiguration7() { $optionsData = [ [ @@ -389,7 +394,7 @@ public function getBundleProductConfiguration7() ]; } - public function getBundleProductConfiguration8() + private function getBundleProductConfiguration8() { $optionsData = [ [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php index 8976da58d0250..02427515ad23e 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php @@ -20,7 +20,8 @@ class DynamicBundleWithSpecialPriceCalculatorTest extends BundlePriceAbstract */ public function testPriceForDynamicBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->prepareFixture($strategyModifiers); + $this->prepareFixture($strategyModifiers, 'bundle_product'); + $bundleProduct = $this->productRepository->get('bundle_product', false, null, true); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -39,10 +40,14 @@ public function testPriceForDynamicBundle(array $strategyModifiers, array $expec ); } + /** + * Test cases for current test + * @return array + */ public function getTestCases() { return [ - 'Testing price for dynamic bundle product with special price and sub items Configuration #1' => [ + '#1 Testing price for dynamic bundle product with special price and sub items Configuration #1' => [ 'strategy' => $this->getBundleConfiguration1(), 'expectedResults' => [ // 0.5 * 10 @@ -51,7 +56,7 @@ public function getTestCases() 'maximalPrice' => 5 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #2' => [ + '#2 Testing price for dynamic bundle product with special price and sub items Configuration #2' => [ 'strategy' => $this->getBundleConfiguration2(), 'expectedResults' => [ // 0.5 * 2 * 10 @@ -60,7 +65,7 @@ public function getTestCases() 'maximalPrice' => 10 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #3' => [ + '#3 Testing price for dynamic bundle product with special price and sub items Configuration #3' => [ 'strategy' => $this->getBundleConfiguration3(), 'expectedResults' => [ // 0.5 * 1 * 10 @@ -69,7 +74,7 @@ public function getTestCases() 'maximalPrice' => 35 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #4' => [ + '#4 Testing price for dynamic bundle product with special price and sub items Configuration #4' => [ 'strategy' => $this->getBundleConfiguration4(), 'expectedResults' => [ // 0.5 * 1 * 10 @@ -78,7 +83,7 @@ public function getTestCases() 'maximalPrice' => 35 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #5' => [ + '#5 Testing price for dynamic bundle product with special price and sub items Configuration #5' => [ 'strategy' => $this->getBundleConfiguration5(), 'expectedResults' => [ // 0.5 * 1 * 10 @@ -87,7 +92,7 @@ public function getTestCases() 'maximalPrice' => 30 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #6' => [ + '#6 Testing price for dynamic bundle product with special price and sub items Configuration #6' => [ 'strategy' => $this->getBundleConfiguration6(), 'expectedResults' => [ // 0.5 * (1 * 10 + 1 * 10) @@ -96,7 +101,7 @@ public function getTestCases() 'maximalPrice' => 65 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #7' => [ + '#7 Testing price for dynamic bundle product with special price and sub items Configuration #7' => [ 'strategy' => $this->getBundleConfiguration7(), 'expectedResults' => [ // 0.5 * (1 * 10) @@ -105,7 +110,7 @@ public function getTestCases() 'maximalPrice' => 65 ] ], - 'Testing price for dynamic bundle product with special price and sub items Configuration #8' => [ + '#8 Testing price for dynamic bundle product with special price and sub items Configuration #8' => [ 'strategy' => $this->getBundleConfiguration8(), 'expectedResults' => [ // 0.5 * (1 * 10) @@ -114,7 +119,7 @@ public function getTestCases() 'maximalPrice' => 65 ] ], - 'Testing price for dynamic bundle product with sub item product that has special price' => [ + '#9 Testing price for dynamic bundle product with sub item product that has special price' => [ 'strategy' => $this->getBundleConfiguration9(), 'expectedResults' => [ // 1 * 3.5 @@ -123,7 +128,7 @@ public function getTestCases() 'maximalPrice' => 20 ] ], - 'Testing price for dynamic bundle product with special price on it and on sub item' => [ + '#10 Testing price for dynamic bundle product with special price on it and on sub item' => [ 'strategy' => $this->getBundleConfiguration10(), 'expectedResults' => [ // 0.5 * 1 * 3.5 @@ -135,7 +140,7 @@ public function getTestCases() ]; } - public function getBundleConfiguration1() + private function getBundleConfiguration1() { $optionsData = [ [ @@ -163,7 +168,7 @@ public function getBundleConfiguration1() ]; } - public function getBundleConfiguration2() + private function getBundleConfiguration2() { $optionsData = [ [ @@ -191,7 +196,7 @@ public function getBundleConfiguration2() ]; } - public function getBundleConfiguration3() + private function getBundleConfiguration3() { $optionsData = [ [ @@ -223,7 +228,7 @@ public function getBundleConfiguration3() ]; } - public function getBundleConfiguration4() + private function getBundleConfiguration4() { $optionsData = [ [ @@ -255,7 +260,7 @@ public function getBundleConfiguration4() ]; } - public function getBundleConfiguration5() + private function getBundleConfiguration5() { $optionsData = [ [ @@ -287,7 +292,7 @@ public function getBundleConfiguration5() ]; } - public function getBundleConfiguration6() + private function getBundleConfiguration6() { $optionsData = [ [ @@ -334,7 +339,7 @@ public function getBundleConfiguration6() ]; } - public function getBundleConfiguration7() + private function getBundleConfiguration7() { $optionsData = [ [ @@ -381,7 +386,7 @@ public function getBundleConfiguration7() ]; } - public function getBundleConfiguration8() + private function getBundleConfiguration8() { $optionsData = [ [ @@ -428,7 +433,7 @@ public function getBundleConfiguration8() ]; } - public function getBundleConfiguration9() + private function getBundleConfiguration9() { $optionsData = [ [ @@ -460,7 +465,7 @@ public function getBundleConfiguration9() ]; } - public function getBundleConfiguration10() + private function getBundleConfiguration10() { $optionsData = [ [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php index 9612279da292e..b8a71e6dafdf0 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php @@ -24,14 +24,15 @@ protected function setUp() } /** - * @param $strategyModifiers array - * @param $expectedResults array + * @param array $strategyModifiers + * @param array $expectedResults * @dataProvider getTestCases * @magentoAppIsolation enabled */ public function testPriceForDynamicBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->prepareFixture($strategyModifiers); + $this->prepareFixture($strategyModifiers, 'bundle_product'); + $bundleProduct = $this->productRepository->get('bundle_product', false, null, true); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -50,10 +51,14 @@ public function testPriceForDynamicBundle(array $strategyModifiers, array $expec ); } + /** + * Test cases for current test + * @return array + */ public function getTestCases() { return [ - 'Testing product price with tier price and sub items Configuration #1' => [ + '#1 Testing product price with tier price and sub items Configuration #1' => [ 'strategy' => $this->getBundleConfiguration1(), 'expectedResults' => [ // 0.5 * 10 @@ -62,7 +67,7 @@ public function getTestCases() 'maximalPrice' => 5 ] ], - 'Testing product price with tier price and sub items Configuration #2' => [ + '#2 Testing product price with tier price and sub items Configuration #2' => [ 'strategy' => $this->getBundleConfiguration2(), 'expectedResults' => [ // 0.5 * 2 * 10 @@ -71,7 +76,7 @@ public function getTestCases() 'maximalPrice' => 10 ] ], - 'Testing product price with tier price and sub items Configuration #3' => [ + '#3 Testing product price with tier price and sub items Configuration #3' => [ 'strategy' => $this->getBundleConfiguration3(), 'expectedResults' => [ // 0.5 * 1 * 10 @@ -80,7 +85,7 @@ public function getTestCases() 'maximalPrice' => 35 ] ], - 'Testing product price with tier price and sub items Configuration #4' => [ + '#4 Testing product price with tier price and sub items Configuration #4' => [ 'strategy' => $this->getBundleConfiguration4(), 'expectedResults' => [ // 0.5 * 1 * 10 @@ -89,7 +94,7 @@ public function getTestCases() 'maximalPrice' => 35 ] ], - 'Testing product price with tier price and sub items Configuration #5' => [ + '#5 Testing product price with tier price and sub items Configuration #5' => [ 'strategy' => $this->getBundleConfiguration5(), 'expectedResults' => [ // 0.5 * 1 * 10 @@ -98,7 +103,7 @@ public function getTestCases() 'maximalPrice' => 30 ] ], - 'Testing product price with tier price and sub items Configuration #6' => [ + '#6 Testing product price with tier price and sub items Configuration #6' => [ 'strategy' => $this->getBundleConfiguration6(), 'expectedResults' => [ // 0.5 * (1 * 10 + 1 * 10) @@ -107,7 +112,7 @@ public function getTestCases() 'maximalPrice' => 65 ] ], - 'Testing product price with tier price and sub items Configuration #7' => [ + '#7 Testing product price with tier price and sub items Configuration #7' => [ 'strategy' => $this->getBundleConfiguration7(), 'expectedResults' => [ // 0.5 * (1 * 10) @@ -116,7 +121,7 @@ public function getTestCases() 'maximalPrice' => 65 ] ], - 'Testing product price with tier price and sub items Configuration #8' => [ + '#8 Testing product price with tier price and sub items Configuration #8' => [ 'strategy' => $this->getBundleConfiguration8(), 'expectedResults' => [ // 0.5 * (1 * 10) @@ -125,7 +130,7 @@ public function getTestCases() 'maximalPrice' => 65 ] ], - 'Testing price for dynamic bundle product with tier price on it and on sub item' => [ + '#9 Testing price for dynamic bundle product with tier price on it and on sub item' => [ 'strategy' => $this->getBundleConfiguration10(), 'expectedResults' => [ // 0.5 * 1 * 2.5 @@ -137,7 +142,7 @@ public function getTestCases() ]; } - public function getBundleConfiguration1() + private function getBundleConfiguration1() { $optionsData = [ [ @@ -171,7 +176,7 @@ public function getBundleConfiguration1() ]; } - public function getBundleConfiguration2() + private function getBundleConfiguration2() { $optionsData = [ [ @@ -205,7 +210,7 @@ public function getBundleConfiguration2() ]; } - public function getBundleConfiguration3() + private function getBundleConfiguration3() { $optionsData = [ [ @@ -243,7 +248,7 @@ public function getBundleConfiguration3() ]; } - public function getBundleConfiguration4() + private function getBundleConfiguration4() { $optionsData = [ [ @@ -281,7 +286,7 @@ public function getBundleConfiguration4() ]; } - public function getBundleConfiguration5() + private function getBundleConfiguration5() { $optionsData = [ [ @@ -319,7 +324,7 @@ public function getBundleConfiguration5() ]; } - public function getBundleConfiguration6() + private function getBundleConfiguration6() { $optionsData = [ [ @@ -372,7 +377,7 @@ public function getBundleConfiguration6() ]; } - public function getBundleConfiguration7() + private function getBundleConfiguration7() { $optionsData = [ [ @@ -425,7 +430,7 @@ public function getBundleConfiguration7() ]; } - public function getBundleConfiguration8() + private function getBundleConfiguration8() { $optionsData = [ [ @@ -478,7 +483,7 @@ public function getBundleConfiguration8() ]; } - public function getBundleConfiguration10() + private function getBundleConfiguration10() { $optionsData = [ [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php index 5ad26638dea3f..faf0bfcfa3396 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php @@ -22,7 +22,8 @@ class FixedBundlePriceCalculatorTest extends BundlePriceAbstract */ public function testPriceForFixedBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->prepareFixture($strategyModifiers); + $this->prepareFixture($strategyModifiers, 'bundle_product'); + $bundleProduct = $this->productRepository->get('bundle_product', false, null, true); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -50,7 +51,8 @@ public function testPriceForFixedBundle(array $strategyModifiers, array $expecte */ public function testPriceForFixedBundleInWebsiteScope(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->prepareFixture($strategyModifiers); + $this->prepareFixture($strategyModifiers, 'bundle_product'); + $bundleProduct = $this->productRepository->get('bundle_product', false, null, true); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -69,10 +71,14 @@ public function testPriceForFixedBundleInWebsiteScope(array $strategyModifiers, ); } + /** + * Test cases for current test + * @return array + */ public function getTestCases() { return [ - 'Testing price for fixed bundle product with one simple' => [ + '#1 Testing price for fixed bundle product with one simple' => [ 'strategy' => $this->getProductWithOneSimple(), 'expectedResults' => [ // 110 + 10 (price from simple1) @@ -81,7 +87,7 @@ public function getTestCases() 'maximalPrice' => 120 ] ], - 'Testing price for fixed bundle product with three simples and differnt qty' => [ + '#2 Testing price for fixed bundle product with three simples and differnt qty' => [ 'strategy' => $this->getProductWithDifferentQty(), 'expectedResults' => [ // 110 + 10 (min price from simples) @@ -90,7 +96,7 @@ public function getTestCases() 'maximalPrice' => 170 ] ], - 'Testing price for fixed bundle product with three simples and differnt price' => [ + '#3 Testing price for fixed bundle product with three simples and differnt price' => [ 'strategy' => $this->getProductWithDifferentPrice(), 'expectedResults' => [ // 110 + 10 @@ -99,7 +105,7 @@ public function getTestCases() 'maximalPrice' => 170 ] ], - 'Testing price for fixed bundle product with three simples' => [ + '#4 Testing price for fixed bundle product with three simples' => [ 'strategy' => $this->getProductWithSamePrice(), 'expectedResults' => [ // 110 + 10 @@ -111,7 +117,7 @@ public function getTestCases() ]; } - public function getProductWithOneSimple() + private function getProductWithOneSimple() { $optionsData = [ [ @@ -137,7 +143,7 @@ public function getProductWithOneSimple() ]; } - public function getProductWithDifferentQty() + private function getProductWithDifferentQty() { $optionsData = [ [ @@ -175,7 +181,7 @@ public function getProductWithDifferentQty() ]; } - public function getProductWithSamePrice() + private function getProductWithSamePrice() { $optionsData = [ [ @@ -213,7 +219,7 @@ public function getProductWithSamePrice() ]; } - public function getProductWithDifferentPrice() + private function getProductWithDifferentPrice() { $optionsData = [ [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php index 88d9be5e7a9fb..a18929463ea95 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php @@ -22,7 +22,8 @@ class FixedBundleWithCatalogPriceRuleCalculatorTest extends BundlePriceAbstract */ public function testPriceForFixedBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->prepareFixture($strategyModifiers); + $this->prepareFixture($strategyModifiers, 'bundle_product'); + $bundleProduct = $this->productRepository->get('bundle_product', false, null, true); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -41,11 +42,15 @@ public function testPriceForFixedBundle(array $strategyModifiers, array $expecte ); } + /** + * Test cases for current test + * @return array + */ public function getTestCases() { return [ ' - Testing price for fixed bundle product + #1 Testing price for fixed bundle product with catalog price rule and without sub items and options ' => [ 'strategy' => $this->getEmptyProductStrategy(), @@ -59,7 +64,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #2 Testing price for fixed bundle product with catalog price rule, fixed sub items and fixed options ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( @@ -76,7 +81,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #3 Testing price for fixed bundle product with catalog price rule, percent sub items and percent options ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( @@ -93,7 +98,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #4 Testing price for fixed bundle product with catalog price rule, fixed sub items and percent options ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( @@ -110,7 +115,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #5 Testing price for fixed bundle product with catalog price rule, percent sub items and fixed options ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( @@ -127,7 +132,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #6 Testing price for fixed bundle product with catalog price rule, fixed sub items and fixed options Configuration #1 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration1( @@ -144,7 +149,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #7 Testing price for fixed bundle product with catalog price rule, percent sub items and percent options Configuration #1 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration1( @@ -161,7 +166,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #8 Testing price for fixed bundle product with catalog price rule, fixed sub items and percent options Configuration #1 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration1( @@ -178,7 +183,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #9 Testing price for fixed bundle product with catalog price rule, percent sub items and fixed options Configuration #1 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration1( @@ -195,7 +200,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #10 Testing price for fixed bundle product with catalog price rule, fixed sub items and fixed options Configuration #2 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration2( @@ -212,7 +217,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #11 Testing price for fixed bundle product with catalog price rule, percent sub items and percent options Configuration #2 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration2( @@ -229,7 +234,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #12 Testing price for fixed bundle product with catalog price rule, fixed sub items and percent options Configuration #2 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration2( @@ -246,7 +251,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #13 Testing price for fixed bundle product with catalog price rule, percent sub items and fixed options Configuration #2 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration2( @@ -263,7 +268,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #14 Testing price for fixed bundle product with catalog price rule, fixed sub items and fixed options Configuration #3 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration3( @@ -280,7 +285,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #15 Testing price for fixed bundle product with catalog price rule, percent sub items and percent options Configuration #3 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration3( @@ -297,7 +302,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #16 Testing price for fixed bundle product with catalog price rule, fixed sub items and percent options Configuration #3 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration3( @@ -314,7 +319,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #17 Testing price for fixed bundle product with catalog price rule, percent sub items and fixed options Configuration #3 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration3( @@ -331,7 +336,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #18 Testing price for fixed bundle product with catalog price rule, fixed sub items and fixed options Configuration #4 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration4( @@ -348,7 +353,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #19 Testing price for fixed bundle product with catalog price rule, percent sub items and percent options Configuration #4 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration4( @@ -365,7 +370,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #20 Testing price for fixed bundle product with catalog price rule, fixed sub items and percent options Configuration #4 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration4( @@ -382,7 +387,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #21 Testing price for fixed bundle product with catalog price rule, percent sub items and fixed options Configuration #4 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration4( @@ -399,7 +404,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #22 Testing price for fixed bundle product with catalog price rule, fixed sub items and fixed options Configuration #5 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration5( @@ -416,7 +421,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #23 Testing price for fixed bundle product with catalog price rule, percent sub items and percent options Configuration #5 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration5( @@ -433,7 +438,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #24 Testing price for fixed bundle product with catalog price rule, fixed sub items and percent options Configuration #5 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration5( @@ -450,7 +455,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #25 Testing price for fixed bundle product with catalog price rule, percent sub items and fixed options Configuration #5 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration5( @@ -467,7 +472,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #26 Testing price for fixed bundle product with catalog price rule, fixed sub items and fixed options Configuration #6 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration6( @@ -484,7 +489,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #27 Testing price for fixed bundle product with catalog price rule, percent sub items and percent options Configuration #6 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration6( @@ -501,7 +506,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #28 Testing price for fixed bundle product with catalog price rule, fixed sub items and percent options Configuration #6 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration6( @@ -518,7 +523,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #29 Testing price for fixed bundle product with catalog price rule, percent sub items and fixed options Configuration #6 ' => [ 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration6( @@ -536,12 +541,12 @@ public function getTestCases() ]; } - public function getEmptyProductStrategy() + private function getEmptyProductStrategy() { return []; } - public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $customOptionsPriceType) + private function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -582,7 +587,7 @@ public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $ ]; } - public function getProductSubItemsAndOptionsStrategyConfiguration1($selectionsPriceType, $customOptionsPriceType) + private function getProductSubItemsAndOptionsStrategyConfiguration1($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -623,7 +628,7 @@ public function getProductSubItemsAndOptionsStrategyConfiguration1($selectionsPr ]; } - public function getProductSubItemsAndOptionsStrategyConfiguration2($selectionsPriceType, $customOptionsPriceType) + private function getProductSubItemsAndOptionsStrategyConfiguration2($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -664,7 +669,7 @@ public function getProductSubItemsAndOptionsStrategyConfiguration2($selectionsPr ]; } - public function getProductSubItemsAndOptionsStrategyConfiguration3($selectionsPriceType, $customOptionsPriceType) + private function getProductSubItemsAndOptionsStrategyConfiguration3($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -711,7 +716,7 @@ public function getProductSubItemsAndOptionsStrategyConfiguration3($selectionsPr ]; } - public function getProductSubItemsAndOptionsStrategyConfiguration4($selectionsPriceType, $customOptionsPriceType) + private function getProductSubItemsAndOptionsStrategyConfiguration4($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -758,7 +763,7 @@ public function getProductSubItemsAndOptionsStrategyConfiguration4($selectionsPr ]; } - public function getProductSubItemsAndOptionsStrategyConfiguration5($selectionsPriceType, $customOptionsPriceType) + private function getProductSubItemsAndOptionsStrategyConfiguration5($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -805,7 +810,7 @@ public function getProductSubItemsAndOptionsStrategyConfiguration5($selectionsPr ]; } - public function getProductSubItemsAndOptionsStrategyConfiguration6($selectionsPriceType, $customOptionsPriceType) + private function getProductSubItemsAndOptionsStrategyConfiguration6($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php index e178087e0cfc7..092c35fc5db3c 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php @@ -22,7 +22,8 @@ class FixedBundleWithSpecialPriceCalculatorTest extends BundlePriceAbstract */ public function testPriceForFixedBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->prepareFixture($strategyModifiers); + $this->prepareFixture($strategyModifiers, 'bundle_product'); + $bundleProduct = $this->productRepository->get('bundle_product', false, null, true); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -41,11 +42,15 @@ public function testPriceForFixedBundle(array $strategyModifiers, array $expecte ); } + /** + * Test cases for current test + * @return array + */ public function getTestCases() { return [ ' - Testing price for fixed bundle product + #1 Testing price for fixed bundle product without any discounts, sub items and options ' => [ 'strategy' => $this->getEmptyProductStrategy(), @@ -59,7 +64,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #2 Testing price for fixed bundle product with special price and without any sub items and options ' => [ 'strategy' => $this->getEmptyProductWithSpecialPriceStrategy(), @@ -73,7 +78,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #3 Testing price for fixed bundle product with fixed sub items, fixed options and without any discounts ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( @@ -90,7 +95,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #4 Testing price for fixed bundle product with percent sub items, percent options and without any discounts ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( @@ -107,7 +112,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #5 Testing price for fixed bundle product with fixed sub items, percent options and without any discounts ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( @@ -124,7 +129,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #6 Testing price for fixed bundle product with percent sub items, fixed options and without any discounts ' => [ 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( @@ -141,7 +146,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #7 Testing price for fixed bundle product with special price, fixed sub items and fixed options Configuration #1 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( @@ -158,7 +163,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #8 Testing price for fixed bundle product with special price, percent sub items and percent options Configuration #1 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( @@ -175,7 +180,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #9 Testing price for fixed bundle product with special price, fixed sub items and percent options Configuration #1 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( @@ -192,7 +197,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #10 Testing price for fixed bundle product with special price, percent sub items and fixed options Configuration #1 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( @@ -209,7 +214,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #11 Testing price for fixed bundle product with special price, fixed sub items and fixed options Configuration #2 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( @@ -226,7 +231,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #12 Testing price for fixed bundle product with special price, percent sub items and percent options Configuration #2 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( @@ -243,7 +248,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #13 Testing price for fixed bundle product with special price, fixed sub items and percent options Configuration #2 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( @@ -260,7 +265,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #14 Testing price for fixed bundle product with special price, percent sub items and fixed options Configuration #2 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( @@ -277,7 +282,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #15 Testing price for fixed bundle product with special price, fixed sub items and fixed options Configuration #3 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( @@ -294,7 +299,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #16 Testing price for fixed bundle product with special price, percent sub items and percent options Configuration #3 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( @@ -311,7 +316,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #17 Testing price for fixed bundle product with special price, fixed sub items and percent options Configuration #3 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( @@ -328,7 +333,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #18 Testing price for fixed bundle product with special price, percent sub items and fixed options Configuration #3 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( @@ -345,7 +350,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #19 Testing price for fixed bundle product with special price, fixed sub items and fixed options Configuration #4 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( @@ -362,7 +367,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #20 Testing price for fixed bundle product with special price, percent sub items and percent options Configuration #4 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( @@ -379,7 +384,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #21 Testing price for fixed bundle product with special price, fixed sub items and percent options Configuration #4 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( @@ -396,7 +401,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #22 Testing price for fixed bundle product with special price, percent sub items and fixed options Configuration #4 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( @@ -413,7 +418,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #23 Testing price for fixed bundle product with special price, fixed sub items and fixed options Configuration #5 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( @@ -430,7 +435,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #24 Testing price for fixed bundle product with special price, percent sub items and percent options Configuration #5 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( @@ -447,7 +452,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #25 Testing price for fixed bundle product with special price, fixed sub items and percent options Configuration #5 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( @@ -464,7 +469,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #26 Testing price for fixed bundle product with special price, percent sub items and fixed options Configuration #5 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( @@ -481,7 +486,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #27 Testing price for fixed bundle product with special price, fixed sub items and fixed options Configuration #6 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( @@ -498,7 +503,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #28 Testing price for fixed bundle product with special price, percent sub items and percent options Configuration #6 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( @@ -515,7 +520,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #29 Testing price for fixed bundle product with special price, fixed sub items and percent options Configuration #6 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( @@ -532,7 +537,7 @@ public function getTestCases() ], ' - Testing price for fixed bundle product + #30 Testing price for fixed bundle product with special price, percent sub items and fixed options Configuration #6 ' => [ 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( @@ -550,12 +555,12 @@ public function getTestCases() ]; } - public function getEmptyProductStrategy() + private function getEmptyProductStrategy() { return []; } - public function getEmptyProductWithSpecialPriceStrategy() + private function getEmptyProductWithSpecialPriceStrategy() { return [ [ @@ -565,7 +570,7 @@ public function getEmptyProductWithSpecialPriceStrategy() ]; } - public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $customOptionsPriceType) + private function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -606,7 +611,7 @@ public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $ ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( $selectionsPriceType, $customOptionsPriceType ) { @@ -653,7 +658,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( $selectionsPriceType, $customOptionsPriceType ) { @@ -700,7 +705,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( $selectionsPriceType, $customOptionsPriceType ) { @@ -753,7 +758,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( $selectionsPriceType, $customOptionsPriceType ) { @@ -806,7 +811,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( $selectionsPriceType, $customOptionsPriceType ) { @@ -859,7 +864,7 @@ public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguratio ]; } - public function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( $selectionsPriceType, $customOptionsPriceType ) { diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php index 949f3dc80b5e7..4e4e2dd497c98 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php @@ -34,7 +34,8 @@ protected function setUp() */ public function testPriceForFixedBundle(array $strategyModifiers, array $expectedResults) { - $bundleProduct = $this->prepareFixture($strategyModifiers); + $this->prepareFixture($strategyModifiers, 'bundle_product'); + $bundleProduct = $this->productRepository->get('bundle_product', false, null, true); /** @var \Magento\Framework\Pricing\PriceInfo\Base $priceInfo */ $priceInfo = $bundleProduct->getPriceInfo(); @@ -54,14 +55,14 @@ public function testPriceForFixedBundle(array $strategyModifiers, array $expecte } /** - * Test cases for fixed bundle product + * Test cases for current test * @return array */ public function getTestCases() { return [ - 'Testing product price with tier price and without any sub items and options' => [ + '#1 Testing product price with tier price and without any sub items and options' => [ 'strategy' => $this->getEmptyProduct(), 'expectedResults' => [ // 110 * 0.5 @@ -72,7 +73,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, fixed sub items and fixed options Configuration #1' => [ + '#2 Testing product price with tier price, fixed sub items and fixed options Configuration #1' => [ 'strategy' => $this->getProductConfiguration1( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED @@ -86,7 +87,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, percent sub items and percent options Configuration #1' => [ + '#3 Testing product price with tier price, percent sub items and percent options Configuration #1' => [ 'strategy' => $this->getProductConfiguration1( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT @@ -100,7 +101,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, fixed sub items and percent options Configuration #1' => [ + '#4 Testing product price with tier price, fixed sub items and percent options Configuration #1' => [ 'strategy' => $this->getProductConfiguration1( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT @@ -114,7 +115,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, percent sub items and fixed options Configuration #1' => [ + '#5 Testing product price with tier price, percent sub items and fixed options Configuration #1' => [ 'strategy' => $this->getProductConfiguration1( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED @@ -128,7 +129,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, fixed sub items and fixed options Configuration #2' => [ + '#6 Testing product price with tier price, fixed sub items and fixed options Configuration #2' => [ 'strategy' => $this->getProductConfiguration2( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED @@ -142,7 +143,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, percent sub items and percent options Configuration #2' => [ + '#7 Testing product price with tier price, percent sub items and percent options Configuration #2' => [ 'strategy' => $this->getProductConfiguration2( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT @@ -156,7 +157,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, fixed sub items and percent options Configuration #2' => [ + '#8 Testing product price with tier price, fixed sub items and percent options Configuration #2' => [ 'strategy' => $this->getProductConfiguration2( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT @@ -170,7 +171,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, percent sub items and fixed options Configuration #2' => [ + '#9 Testing product price with tier price, percent sub items and fixed options Configuration #2' => [ 'strategy' => $this->getProductConfiguration2( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED @@ -184,7 +185,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, fixed sub items and fixed options Configuration #3' => [ + '#10 Testing product price with tier price, fixed sub items and fixed options Configuration #3' => [ 'strategy' => $this->getProductConfiguration3( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED @@ -198,7 +199,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, percent sub items and percent options Configuration #3' => [ + '#11 Testing product price with tier price, percent sub items and percent options Configuration #3' => [ 'strategy' => $this->getProductConfiguration3( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT @@ -212,7 +213,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, fixed sub items and percent options Configuration #3' => [ + '#12 Testing product price with tier price, fixed sub items and percent options Configuration #3' => [ 'strategy' => $this->getProductConfiguration3( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT @@ -226,7 +227,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, percent sub items and fixed options Configuration #3' => [ + '#13 Testing product price with tier price, percent sub items and fixed options Configuration #3' => [ 'strategy' => $this->getProductConfiguration3( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED @@ -240,7 +241,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, fixed sub items and fixed options Configuration #4' => [ + '#14 Testing product price with tier price, fixed sub items and fixed options Configuration #4' => [ 'strategy' => $this->getProductConfiguration4( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED @@ -254,7 +255,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, percent sub items and percent options Configuration #4' => [ + '#15 Testing product price with tier price, percent sub items and percent options Configuration #4' => [ 'strategy' => $this->getProductConfiguration4( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT @@ -268,7 +269,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, fixed sub items and percent options Configuration #4' => [ + '#16 Testing product price with tier price, fixed sub items and percent options Configuration #4' => [ 'strategy' => $this->getProductConfiguration4( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT @@ -282,7 +283,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, percent sub items and fixed options Configuration #4' => [ + '#17 Testing product price with tier price, percent sub items and fixed options Configuration #4' => [ 'strategy' => $this->getProductConfiguration4( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED @@ -296,7 +297,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, fixed sub items and fixed options Configuration #5' => [ + '#18 Testing product price with tier price, fixed sub items and fixed options Configuration #5' => [ 'strategy' => $this->getProductConfiguration5( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED @@ -310,7 +311,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, percent sub items and percent options Configuration #5' => [ + '#19 Testing product price with tier price, percent sub items and percent options Configuration #5' => [ 'strategy' => $this->getProductConfiguration5( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT @@ -324,7 +325,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, fixed sub items and percent options Configuration #5' => [ + '#20 Testing product price with tier price, fixed sub items and percent options Configuration #5' => [ 'strategy' => $this->getProductConfiguration5( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT @@ -338,7 +339,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, percent sub items and fixed options Configuration #5' => [ + '#21 Testing product price with tier price, percent sub items and fixed options Configuration #5' => [ 'strategy' => $this->getProductConfiguration5( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED @@ -352,7 +353,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, fixed sub items and fixed options Configuration #6' => [ + '#22 Testing product price with tier price, fixed sub items and fixed options Configuration #6' => [ 'strategy' => $this->getProductConfiguration6( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED @@ -366,7 +367,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, percent sub items and percent options Configuration #6' => [ + '#23 Testing product price with tier price, percent sub items and percent options Configuration #6' => [ 'strategy' => $this->getProductConfiguration6( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT @@ -380,7 +381,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, fixed sub items and percent options Configuration #6' => [ + '#24 Testing product price with tier price, fixed sub items and percent options Configuration #6' => [ 'strategy' => $this->getProductConfiguration6( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT @@ -394,7 +395,7 @@ public function getTestCases() ] ], - 'Testing product price with tier price, percent sub items and fixed options Configuration #6' => [ + '#25 Testing product price with tier price, percent sub items and fixed options Configuration #6' => [ 'strategy' => $this->getProductConfiguration6( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED @@ -411,7 +412,7 @@ public function getTestCases() ]; } - public function getEmptyProduct() + private function getEmptyProduct() { $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, @@ -427,7 +428,7 @@ public function getEmptyProduct() ]; } - public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $customOptionsPriceType) + private function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -478,7 +479,7 @@ public function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $ ]; } - public function getProductConfiguration1($selectionsPriceType, $customOptionsPriceType) + private function getProductConfiguration1($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -529,7 +530,7 @@ public function getProductConfiguration1($selectionsPriceType, $customOptionsPri ]; } - public function getProductConfiguration2($selectionsPriceType, $customOptionsPriceType) + private function getProductConfiguration2($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -580,7 +581,7 @@ public function getProductConfiguration2($selectionsPriceType, $customOptionsPri ]; } - public function getProductConfiguration3($selectionsPriceType, $customOptionsPriceType) + private function getProductConfiguration3($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -637,7 +638,7 @@ public function getProductConfiguration3($selectionsPriceType, $customOptionsPri ]; } - public function getProductConfiguration4($selectionsPriceType, $customOptionsPriceType) + private function getProductConfiguration4($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -694,7 +695,7 @@ public function getProductConfiguration4($selectionsPriceType, $customOptionsPri ]; } - public function getProductConfiguration5($selectionsPriceType, $customOptionsPriceType) + private function getProductConfiguration5($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -751,7 +752,7 @@ public function getProductConfiguration5($selectionsPriceType, $customOptionsPri ]; } - public function getProductConfiguration6($selectionsPriceType, $customOptionsPriceType) + private function getProductConfiguration6($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php index fb04b268bfdfe..de45c9e06b447 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php @@ -42,7 +42,8 @@ public function testIsSaleableOnEnabledStatus() $this->assertTrue( $bundleProduct->isSalable(), - 'Bundle product supposed to be saleable if his status is enabled' + 'Bundle product supposed to be saleable + if his status is enabled' ); } @@ -59,7 +60,8 @@ public function testIsSaleableOnDisabledStatus() $this->assertFalse( $bundleProduct->isSalable(), - 'Bundle product supposed to be non saleable if his status is disabled' + 'Bundle product supposed to be non saleable + if his status is disabled' ); } @@ -78,7 +80,8 @@ public function testIsSaleableOnEnabledStatusAndIsSalableIsTrue() $this->assertTrue( $bundleProduct->isSalable(), - 'Bundle product supposed to be saleable if his status is enabled and it has data is_salable = true' + 'Bundle product supposed to be saleable + if his status is enabled and it has data is_salable = true' ); } @@ -97,7 +100,8 @@ public function testIsSaleableOnEnabledStatusAndIsSalableIsFalse() $this->assertFalse( $bundleProduct->isSalable(), - 'Bundle product supposed to be non saleable if his status is enabled but his data is_salable = false' + 'Bundle product supposed to be non saleable + if his status is enabled but his data is_salable = false' ); } @@ -114,7 +118,8 @@ public function testIsSaleableOnAllItemsSalableIsTrue() $this->assertTrue( $bundleProduct->isSalable(), - 'Bundle product supposed to be saleable if it has data all_items_salable = true' + 'Bundle product supposed to be saleable + if it has data all_items_salable = true' ); } @@ -131,7 +136,8 @@ public function testIsSaleableOnAllItemsSalableIsFalse() $this->assertFalse( $bundleProduct->isSalable(), - 'Bundle product supposed to be non saleable if it has data all_items_salable = false' + 'Bundle product supposed to be non saleable + if it has data all_items_salable = false' ); } @@ -158,7 +164,8 @@ public function testIsSaleableOnBundleWithoutOptions() $this->assertFalse( $bundleProduct->isSalable(), - 'Bundle product supposed to be non saleable if it has no options' + 'Bundle product supposed to be non saleable + if it has no options' ); } @@ -187,7 +194,8 @@ public function testIsSaleableOnBundleWithoutSelections() $bundleProduct = $this->productRepository->get('bundle-product', false, null, true); $this->assertFalse( $bundleProduct->isSalable(), - 'Bundle product supposed to be non saleable if it has no selections' + 'Bundle product supposed to be non saleable + if it has no selections' ); } @@ -211,7 +219,8 @@ public function testIsSaleableOnBundleWithoutSaleableSelections() $this->assertFalse( $bundleProduct->isSalable(), - 'Bundle product supposed to be non saleable if all his selections are not saleable' + 'Bundle product supposed to be non saleable + if all his selections are not saleable' ); } @@ -235,7 +244,8 @@ public function testIsSaleableOnBundleWithoutSaleableSelectionsOnRequiredOption( $this->assertFalse( $bundleProduct->isSalable(), - 'Bundle product supposed to be non saleable if it has at least one required option with no saleable selections' + 'Bundle product supposed to be non saleable + if it has at least one required option with no saleable selections' ); } @@ -254,7 +264,8 @@ public function testIsSaleableOnBundleWithNotEnoughQtyOfSelection() $this->assertFalse( $bundleProduct->isSalable(), - 'Bundle product supposed to be non saleable if there are not enough qty of selections on required options' + 'Bundle product supposed to be non saleable + if there are not enough qty of selections on required options' ); } @@ -288,7 +299,8 @@ public function testIsSaleableOnBundleWithSelectionCanChangeQty() $this->assertTrue( $bundleProduct->isSalable(), - 'Bundle product supposed to be saleable if all his selections have selection_can_change_qty = 1' + 'Bundle product supposed to be saleable + if all his selections have selection_can_change_qty = 1' ); } @@ -324,7 +336,8 @@ public function testIsSaleableOnBundleWithoutRequiredOptions() $this->assertFalse( $bundleProduct->isSalable(), - 'Bundle product supposed to be not saleable if all his options are not required and selections are not saleable' + 'Bundle product supposed to be not saleable + if all his options are not required and selections are not saleable' ); } @@ -362,7 +375,8 @@ public function testIsSaleableOnBundleWithOneSaleableSelection() $this->assertTrue( $bundleProduct->isSalable(), - 'Bundle product supposed to be saleable if it has at least one not required option with saleable selection' + 'Bundle product supposed to be saleable + if it has at least one not required option with saleable selection' ); } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php index 218ae90d4509f..9918cb0c743fb 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product.php @@ -15,8 +15,8 @@ ->setId(42) ->setAttributeSetId(4) ->setWebsiteIds([1]) - ->setName('Spherical Horse in a Vacuum') - ->setSku('spherical_horse_in_a_vacuum') + ->setName('Spherical Bundle Product in a Vacuum') + ->setSku('bundle_product') ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php index bb41cddb8e0a4..33db954a6eee8 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/dynamic_bundle_product_rollback.php @@ -15,7 +15,7 @@ $registry->register('isSecureArea', true); try { - $product = $productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + $product = $productRepository->get('bundle_product', false, null, true); $productRepository->delete($product); } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { //Product already removed diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product.php index 7b501db8e89a4..a8f3974f6584e 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product.php @@ -15,8 +15,8 @@ ->setId(42) ->setAttributeSetId(4) ->setWebsiteIds([1]) - ->setName('Spherical Horse in a Vacuum') - ->setSku('spherical_horse_in_a_vacuum') + ->setName('Spherical Bundle Product in a Vacuum') + ->setSku('bundle_product') ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php index bb41cddb8e0a4..33db954a6eee8 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/PriceCalculator/fixed_bundle_product_rollback.php @@ -15,7 +15,7 @@ $registry->register('isSecureArea', true); try { - $product = $productRepository->get('spherical_horse_in_a_vacuum', false, null, true); + $product = $productRepository->get('bundle_product', false, null, true); $productRepository->delete($product); } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { //Product already removed diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php index 5e96221737241..0075f3ab8ec86 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php @@ -207,4 +207,4 @@ $product->setExtensionAttributes($extension); } -$productRepository->save($product, true); \ No newline at end of file +$productRepository->save($product, true); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product_rollback.php index f65dbbbb5435b..a24861525f009 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product_rollback.php @@ -13,7 +13,8 @@ $registry->register('isSecureArea', true); /** @var $product \Magento\Catalog\Model\Product */ -$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); +$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); try { $product = $productRepository->get('bundle-product'); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php index 04def919e6aa7..08624244df162 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php @@ -4,7 +4,8 @@ * See COPYING.txt for license details. */ -$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); +$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); /** @var $product \Magento\Catalog\Model\Product */ $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); @@ -125,4 +126,4 @@ ->setCateroryIds([]) ->setStockData(['use_config_manage_stock' => 1, 'qty' => 15, 'is_qty_decimal' => 0, 'is_in_stock' => 1]); -$productRepository->save($product); \ No newline at end of file +$productRepository->save($product); From 3d13eac787e06191e0230f4c5b194368481b7583 Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Wed, 2 Nov 2016 10:36:53 +0200 Subject: [PATCH 043/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - removed unused testcase --- ...FixedBundleWithTierPriceCalculatorTest.php | 51 ------------------- 1 file changed, 51 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php index 4e4e2dd497c98..7766158967f55 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php @@ -428,57 +428,6 @@ private function getEmptyProduct() ]; } - private function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $customOptionsPriceType) - { - $optionsData = [ - [ - 'title' => 'Op1', - 'required' => true, - 'type' => 'checkbox', - 'links' => [ - [ - 'sku' => 'simple1', - 'qty' => 1, - 'price' => 20, - 'price_type' => $selectionsPriceType - ], - ] - ], - ]; - - $customOptionsData = [ - [ - 'price_type' => $customOptionsPriceType, - 'title' => 'Test Field', - 'type' => 'field', - 'is_require' => 1, - 'price' => 100, - 'sku' => '1-text', - ] - ]; - - $tierPriceData = [ - 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, - 'qty' => 1, - 'value' => 50 - ]; - - return [ - [ - 'modifierName' => 'addTierPrice', - 'data' => [$tierPriceData] - ], - [ - 'modifierName' => 'addSimpleProduct', - 'data' => [$optionsData] - ], - [ - 'modifierName' => 'addCustomOption', - 'data' => [$customOptionsData] - ], - ]; - } - private function getProductConfiguration1($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ From cfae102211d4a9c2cb7a3c48ffbc534a139910b0 Mon Sep 17 00:00:00 2001 From: Michail Slabko Date: Wed, 2 Nov 2016 12:58:41 +0200 Subject: [PATCH 044/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-60096: Fix FAT CreateSimpleProductEntityTest --- .../Observer/AddInventoryDataObserver.php | 40 +++++++++++++++++++ .../Magento/CatalogInventory/etc/events.xml | 3 ++ 2 files changed, 43 insertions(+) create mode 100644 app/code/Magento/CatalogInventory/Observer/AddInventoryDataObserver.php diff --git a/app/code/Magento/CatalogInventory/Observer/AddInventoryDataObserver.php b/app/code/Magento/CatalogInventory/Observer/AddInventoryDataObserver.php new file mode 100644 index 0000000000000..b664b5a80784f --- /dev/null +++ b/app/code/Magento/CatalogInventory/Observer/AddInventoryDataObserver.php @@ -0,0 +1,40 @@ +stockHelper = $stockHelper; + } + + /** + * Add stock information to product + * + * @param EventObserver $observer + * @return void + */ + public function execute(EventObserver $observer) + { + $product = $observer->getEvent()->getProduct(); + if ($product instanceof \Magento\Catalog\Model\Product) { + $this->stockHelper->assignStatusToProduct($product); + } + } +} diff --git a/app/code/Magento/CatalogInventory/etc/events.xml b/app/code/Magento/CatalogInventory/etc/events.xml index 6dd357fda7b65..a1476c2c3f8b1 100644 --- a/app/code/Magento/CatalogInventory/etc/events.xml +++ b/app/code/Magento/CatalogInventory/etc/events.xml @@ -9,6 +9,9 @@ + + + From 1117eac76b88c87cf501d28759b752408a69d152 Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Wed, 2 Nov 2016 13:41:50 +0200 Subject: [PATCH 045/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - refactoring for integration tests --- .../ResourceModel/Selection/Collection.php | 53 +--- .../DynamicBundlePriceCalculatorTest.php | 17 + ...ndleWithCatalogPriceRuleCalculatorTest.php | 91 ++++-- ...icBundleWithSpecialPriceCalculatorTest.php | 100 +++++- ...namicBundleWithTierPriceCalculatorTest.php | 94 +++++- .../FixedBundlePriceCalculatorTest.php | 23 +- ...ndleWithCatalogPriceRuleCalculatorTest.php | 292 +++++++----------- ...edBundleWithSpecialPriceCalculatorTest.php | 177 +++++++---- ...FixedBundleWithTierPriceCalculatorTest.php | 232 ++++++++++---- .../Bundle/Model/Product/IsSaleableTest.php | 28 +- 10 files changed, 689 insertions(+), 418 deletions(-) diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php index afb04e62bf467..d1bbc8e7bbd40 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php @@ -29,7 +29,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection /** * @var \Magento\CatalogRule\Model\ResourceModel\Product\Collection */ - private $catalogRuleProcessor; + private $catalogRuleProcessor = null; /** * Is website scope prices joined to collection @@ -38,57 +38,6 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection */ private $websiteScopePriceJoined = false; - /** - * @inheritDoc - */ - public function __construct( - \Magento\Framework\Data\Collection\EntityFactory $entityFactory, - \Psr\Log\LoggerInterface $logger, - \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy, - \Magento\Framework\Event\ManagerInterface $eventManager, - \Magento\Eav\Model\Config $eavConfig, - \Magento\Framework\App\ResourceConnection $resource, - \Magento\Eav\Model\EntityFactory $eavEntityFactory, - \Magento\Catalog\Model\ResourceModel\Helper $resourceHelper, - \Magento\Framework\Validator\UniversalFactory $universalFactory, - \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Framework\Module\Manager $moduleManager, - \Magento\Catalog\Model\Indexer\Product\Flat\State $catalogProductFlatState, - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - \Magento\Catalog\Model\Product\OptionFactory $productOptionFactory, - \Magento\Catalog\Model\ResourceModel\Url $catalogUrl, - \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, - \Magento\Customer\Model\Session $customerSession, - \Magento\Framework\Stdlib\DateTime $dateTime, - GroupManagementInterface $groupManagement, - \Magento\CatalogRule\Model\ResourceModel\Product\Collection $catalogRuleProcessor = null, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null - ) { - parent::__construct( - $entityFactory, - $logger, - $fetchStrategy, - $eventManager, - $eavConfig, - $resource, - $eavEntityFactory, - $resourceHelper, - $universalFactory, - $storeManager, - $moduleManager, - $catalogProductFlatState, - $scopeConfig, - $productOptionFactory, - $catalogUrl, - $localeDate, - $customerSession, - $dateTime, - $groupManagement, - $connection - ); - $this->catalogRuleProcessor = $catalogRuleProcessor; - } - /** * Initialize collection * diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php index 3cc9939ba38ad..0206bfa38f041 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundlePriceCalculatorTest.php @@ -85,6 +85,7 @@ public function getTestCases() 'maximalPrice' => 10 ] ], + '#2 Testing price for dynamic bundle product with three simples and different qty' => [ 'strategy' => $this->getProductWithDifferentQty(), 'expectedResults' => [ @@ -94,6 +95,7 @@ public function getTestCases() 'maximalPrice' => 100 ] ], + '#3 Testing price for dynamic bundle product with four simples and different price' => [ 'strategy' => $this->getProductWithDifferentPrice(), 'expectedResults' => [ @@ -106,6 +108,11 @@ public function getTestCases() ]; } + /** + * Dynamic bundle product with one simple + * + * @return array + */ private function getProductWithOneSimple() { $optionsData = [ @@ -130,6 +137,11 @@ private function getProductWithOneSimple() ]; } + /** + * Dynamic bundle product with three simples and different qty + * + * @return array + */ private function getProductWithDifferentQty() { $optionsData = [ @@ -162,6 +174,11 @@ private function getProductWithDifferentQty() ]; } + /** + * Dynamic bundle product with three simples and different price + * + * @return array + */ private function getProductWithDifferentPrice() { $optionsData = [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php index 41644729fece3..80ad5e6a85786 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithCatalogPriceRuleCalculatorTest.php @@ -43,12 +43,13 @@ public function testPriceForDynamicBundle(array $strategyModifiers, array $expec /** * Test cases for current test * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function getTestCases() { return [ - '#1 Testing price for dynamic bundle product with sub items and catalog rule price' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy(), + '#1 Testing price for dynamic bundle with one required option' => [ + 'strategy' => $this->getBundleProductConfiguration1(), 'expectedResults' => [ // 10 * 0.9 'minimalPrice' => 9, @@ -58,8 +59,8 @@ public function getTestCases() ] ], - '#2 Testing price for dynamic bundle product with special price, sub items and catalog rule price' => [ - 'strategy' => $this->getBundleProductConfiguration1(), + '#2 Testing price for dynamic bundle with one required option and special price' => [ + 'strategy' => $this->getBundleProductConfiguration2(), 'expectedResults' => [ // 0.5 * 10 * 0.9 'minimalPrice' => 4.5, @@ -69,8 +70,8 @@ public function getTestCases() ] ], - '#3 Testing price for dynamic bundle product with sub items and catalog rule price Configuration #2' => [ - 'strategy' => $this->getBundleProductConfiguration2(), + '#3 Testing price for dynamic bundle with one non required option' => [ + 'strategy' => $this->getBundleProductConfiguration3(), 'expectedResults' => [ // 0.9 * 2 * 10 'minimalPrice' => 18, @@ -80,8 +81,8 @@ public function getTestCases() ] ], - '#4 Testing price for dynamic bundle product with sub items and catalog rule price Configuration #3' => [ - 'strategy' => $this->getBundleProductConfiguration3(), + '#4 Testing price for dynamic bundle with one required checkbox type option and 2 simples' => [ + 'strategy' => $this->getBundleProductConfiguration4(), 'expectedResults' => [ // 0.9 * 1 * 10 'minimalPrice' => 9, @@ -91,8 +92,8 @@ public function getTestCases() ] ], - '#5 Testing price for dynamic bundle product with sub items and catalog rule price Configuration #4' => [ - 'strategy' => $this->getBundleProductConfiguration4(), + '#5 Testing price for dynamic bundle with one required multi type option and 2 simples' => [ + 'strategy' => $this->getBundleProductConfiguration5(), 'expectedResults' => [ // 0.9 * 1 * 10 'minimalPrice' => 9, @@ -102,8 +103,8 @@ public function getTestCases() ] ], - '#6 Testing price for dynamic bundle product with sub items and catalog rule price Configuration #5' => [ - 'strategy' => $this->getBundleProductConfiguration5(), + '#6 Testing price for dynamic bundle with one required radio type option and 2 simples' => [ + 'strategy' => $this->getBundleProductConfiguration6(), 'expectedResults' => [ // 0.9 * 1 * 10 'minimalPrice' => 9, @@ -113,8 +114,8 @@ public function getTestCases() ] ], - '#7 Testing price for dynamic bundle product with sub items and catalog rule price Configuration #6' => [ - 'strategy' => $this->getBundleProductConfiguration6(), + '#7 Testing price for dynamic bundle with two required options' => [ + 'strategy' => $this->getBundleProductConfiguration7(), 'expectedResults' => [ // 0.9 * 1 * 10 + 0.9 * 1 * 10 'minimalPrice' => 18, @@ -124,8 +125,8 @@ public function getTestCases() ] ], - '#8 Testing price for dynamic bundle product with sub items and catalog rule price Configuration #7' => [ - 'strategy' => $this->getBundleProductConfiguration7(), + '#8 Testing price for dynamic bundle with one required option and one non required' => [ + 'strategy' => $this->getBundleProductConfiguration8(), 'expectedResults' => [ // 1 * 0.9 * 10 'minimalPrice' => 9, @@ -135,8 +136,8 @@ public function getTestCases() ] ], - '#9 Testing price for dynamic bundle product with sub items and catalog rule price Configuration #8' => [ - 'strategy' => $this->getBundleProductConfiguration8(), + '#9 Testing price for dynamic bundle with two non required options' => [ + 'strategy' => $this->getBundleProductConfiguration9(), 'expectedResults' => [ // 0.9 * 1 * 10 'minimalPrice' => 9, @@ -148,7 +149,11 @@ public function getTestCases() ]; } - private function getProductWithSubItemsAndOptionsStrategy() + /** + * Dynamic bundle with one required option + * @return array + */ + private function getBundleProductConfiguration1() { $optionsData = [ [ @@ -172,7 +177,11 @@ private function getProductWithSubItemsAndOptionsStrategy() ]; } - private function getBundleProductConfiguration1() + /** + * Dynamic bundle with one required option and special price + * @return array + */ + private function getBundleProductConfiguration2() { $optionsData = [ [ @@ -200,7 +209,11 @@ private function getBundleProductConfiguration1() ]; } - private function getBundleProductConfiguration2() + /** + * Dynamic bundle with one non required option + * @return array + */ + private function getBundleProductConfiguration3() { $optionsData = [ [ @@ -224,7 +237,11 @@ private function getBundleProductConfiguration2() ]; } - private function getBundleProductConfiguration3() + /** + * Dynamic bundle with one required checkbox type option and 2 simples + * @return array + */ + private function getBundleProductConfiguration4() { $optionsData = [ [ @@ -252,7 +269,11 @@ private function getBundleProductConfiguration3() ]; } - private function getBundleProductConfiguration4() + /** + * Dynamic bundle with one required multi type option and 2 simples + * @return array + */ + private function getBundleProductConfiguration5() { $optionsData = [ [ @@ -280,7 +301,11 @@ private function getBundleProductConfiguration4() ]; } - private function getBundleProductConfiguration5() + /** + * Dynamic bundle with one required radio type option and 2 simples + * @return array + */ + private function getBundleProductConfiguration6() { $optionsData = [ [ @@ -308,7 +333,11 @@ private function getBundleProductConfiguration5() ]; } - private function getBundleProductConfiguration6() + /** + * Dynamic bundle with two required options + * @return array + */ + private function getBundleProductConfiguration7() { $optionsData = [ [ @@ -351,7 +380,11 @@ private function getBundleProductConfiguration6() ]; } - private function getBundleProductConfiguration7() + /** + * Dynamic bundle with one required option and one non required + * @return array + */ + private function getBundleProductConfiguration8() { $optionsData = [ [ @@ -394,7 +427,11 @@ private function getBundleProductConfiguration7() ]; } - private function getBundleProductConfiguration8() + /** + * Dynamic bundle with two non required options + * @return array + */ + private function getBundleProductConfiguration9() { $optionsData = [ [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php index 02427515ad23e..8b56a1128b98f 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithSpecialPriceCalculatorTest.php @@ -43,11 +43,15 @@ public function testPriceForDynamicBundle(array $strategyModifiers, array $expec /** * Test cases for current test * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function getTestCases() { return [ - '#1 Testing price for dynamic bundle product with special price and sub items Configuration #1' => [ + ' + #1 Testing price for dynamic bundle + with one required option and special price + ' => [ 'strategy' => $this->getBundleConfiguration1(), 'expectedResults' => [ // 0.5 * 10 @@ -56,7 +60,11 @@ public function getTestCases() 'maximalPrice' => 5 ] ], - '#2 Testing price for dynamic bundle product with special price and sub items Configuration #2' => [ + + ' + #2 Testing price for dynamic bundle + with one non required option and special price + ' => [ 'strategy' => $this->getBundleConfiguration2(), 'expectedResults' => [ // 0.5 * 2 * 10 @@ -65,7 +73,11 @@ public function getTestCases() 'maximalPrice' => 10 ] ], - '#3 Testing price for dynamic bundle product with special price and sub items Configuration #3' => [ + + ' + #3 Testing price for dynamic bundle + with one required checkbox type option, two simples and special price + ' => [ 'strategy' => $this->getBundleConfiguration3(), 'expectedResults' => [ // 0.5 * 1 * 10 @@ -74,7 +86,11 @@ public function getTestCases() 'maximalPrice' => 35 ] ], - '#4 Testing price for dynamic bundle product with special price and sub items Configuration #4' => [ + + ' + #4 Testing price for dynamic bundle + with one required multi type option, two simples and special price + ' => [ 'strategy' => $this->getBundleConfiguration4(), 'expectedResults' => [ // 0.5 * 1 * 10 @@ -83,7 +99,11 @@ public function getTestCases() 'maximalPrice' => 35 ] ], - '#5 Testing price for dynamic bundle product with special price and sub items Configuration #5' => [ + + ' + #5 Testing price for dynamic bundle + with one required radio type option, two simples and special price + ' => [ 'strategy' => $this->getBundleConfiguration5(), 'expectedResults' => [ // 0.5 * 1 * 10 @@ -92,7 +112,11 @@ public function getTestCases() 'maximalPrice' => 30 ] ], - '#6 Testing price for dynamic bundle product with special price and sub items Configuration #6' => [ + + ' + #6 Testing price for dynamic bundle + with two required options and special price + ' => [ 'strategy' => $this->getBundleConfiguration6(), 'expectedResults' => [ // 0.5 * (1 * 10 + 1 * 10) @@ -101,7 +125,11 @@ public function getTestCases() 'maximalPrice' => 65 ] ], - '#7 Testing price for dynamic bundle product with special price and sub items Configuration #7' => [ + + ' + #7 Testing price for dynamic bundle + with one required option, one non required and special price + ' => [ 'strategy' => $this->getBundleConfiguration7(), 'expectedResults' => [ // 0.5 * (1 * 10) @@ -110,7 +138,11 @@ public function getTestCases() 'maximalPrice' => 65 ] ], - '#8 Testing price for dynamic bundle product with special price and sub items Configuration #8' => [ + + ' + #8 Testing price for dynamic bundle + with two non required options and special price + ' => [ 'strategy' => $this->getBundleConfiguration8(), 'expectedResults' => [ // 0.5 * (1 * 10) @@ -119,7 +151,11 @@ public function getTestCases() 'maximalPrice' => 65 ] ], - '#9 Testing price for dynamic bundle product with sub item product that has special price' => [ + + ' + #9 Testing price for dynamic bundle + with one simple product with special price + ' => [ 'strategy' => $this->getBundleConfiguration9(), 'expectedResults' => [ // 1 * 3.5 @@ -128,7 +164,11 @@ public function getTestCases() 'maximalPrice' => 20 ] ], - '#10 Testing price for dynamic bundle product with special price on it and on sub item' => [ + + ' + #10 Testing price for dynamic bundle + with special price and with one simple product with special price + ' => [ 'strategy' => $this->getBundleConfiguration10(), 'expectedResults' => [ // 0.5 * 1 * 3.5 @@ -140,6 +180,10 @@ public function getTestCases() ]; } + /** + * Dynamic bundle with one required option and special price + * @return array + */ private function getBundleConfiguration1() { $optionsData = [ @@ -168,6 +212,10 @@ private function getBundleConfiguration1() ]; } + /** + * Dynamic bundle with one non required option and special price + * @return array + */ private function getBundleConfiguration2() { $optionsData = [ @@ -196,6 +244,10 @@ private function getBundleConfiguration2() ]; } + /** + * Dynamic bundle with one required checkbox type option, two simples and special price + * @return array + */ private function getBundleConfiguration3() { $optionsData = [ @@ -228,6 +280,10 @@ private function getBundleConfiguration3() ]; } + /** + * Dynamic bundle with one required multi type option, two simples and special price + * @return array + */ private function getBundleConfiguration4() { $optionsData = [ @@ -260,6 +316,10 @@ private function getBundleConfiguration4() ]; } + /** + * Dynamic bundle with one required radio type option, two simples and special price + * @return array + */ private function getBundleConfiguration5() { $optionsData = [ @@ -292,6 +352,10 @@ private function getBundleConfiguration5() ]; } + /** + * Dynamic bundle with two required options and special price + * @return array + */ private function getBundleConfiguration6() { $optionsData = [ @@ -339,6 +403,10 @@ private function getBundleConfiguration6() ]; } + /** + * Dynamic bundle with one required option, one non required and special price + * @return array + */ private function getBundleConfiguration7() { $optionsData = [ @@ -386,6 +454,10 @@ private function getBundleConfiguration7() ]; } + /** + * Dynamic bundle with two non required options and special price + * @return array + */ private function getBundleConfiguration8() { $optionsData = [ @@ -433,6 +505,10 @@ private function getBundleConfiguration8() ]; } + /** + * Dynamic bundle with one simple product with special price + * @return array + */ private function getBundleConfiguration9() { $optionsData = [ @@ -465,6 +541,10 @@ private function getBundleConfiguration9() ]; } + /** + * Dynamic bundle with special price and with one simple product with special price + * @return array + */ private function getBundleConfiguration10() { $optionsData = [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php index b8a71e6dafdf0..0be5adcb304f7 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php @@ -54,11 +54,15 @@ public function testPriceForDynamicBundle(array $strategyModifiers, array $expec /** * Test cases for current test * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function getTestCases() { return [ - '#1 Testing product price with tier price and sub items Configuration #1' => [ + ' + #1 Testing product price for dynamic bundle + with one required option and tier price + ' => [ 'strategy' => $this->getBundleConfiguration1(), 'expectedResults' => [ // 0.5 * 10 @@ -67,7 +71,11 @@ public function getTestCases() 'maximalPrice' => 5 ] ], - '#2 Testing product price with tier price and sub items Configuration #2' => [ + + ' + #2 Testing product price for dynamic bundle + with one non required option and tier price + ' => [ 'strategy' => $this->getBundleConfiguration2(), 'expectedResults' => [ // 0.5 * 2 * 10 @@ -76,7 +84,11 @@ public function getTestCases() 'maximalPrice' => 10 ] ], - '#3 Testing product price with tier price and sub items Configuration #3' => [ + + ' + #3 Testing product price for dynamic bundle + with one required checkbox type option and tier price + ' => [ 'strategy' => $this->getBundleConfiguration3(), 'expectedResults' => [ // 0.5 * 1 * 10 @@ -85,7 +97,11 @@ public function getTestCases() 'maximalPrice' => 35 ] ], - '#4 Testing product price with tier price and sub items Configuration #4' => [ + + ' + #4 Testing product price for dynamic bundle + with one required multi type option and tier price + ' => [ 'strategy' => $this->getBundleConfiguration4(), 'expectedResults' => [ // 0.5 * 1 * 10 @@ -94,7 +110,11 @@ public function getTestCases() 'maximalPrice' => 35 ] ], - '#5 Testing product price with tier price and sub items Configuration #5' => [ + + ' + #5 Testing product price for dynamic bundle + with one required radio type option and tier price + ' => [ 'strategy' => $this->getBundleConfiguration5(), 'expectedResults' => [ // 0.5 * 1 * 10 @@ -103,7 +123,11 @@ public function getTestCases() 'maximalPrice' => 30 ] ], - '#6 Testing product price with tier price and sub items Configuration #6' => [ + + ' + #6 Testing product price for dynamic bundle + with two required options and tier price + ' => [ 'strategy' => $this->getBundleConfiguration6(), 'expectedResults' => [ // 0.5 * (1 * 10 + 1 * 10) @@ -112,7 +136,11 @@ public function getTestCases() 'maximalPrice' => 65 ] ], - '#7 Testing product price with tier price and sub items Configuration #7' => [ + + ' + #7 Testing product price for dynamic bundle + with one required option, one non required option and tier price + ' => [ 'strategy' => $this->getBundleConfiguration7(), 'expectedResults' => [ // 0.5 * (1 * 10) @@ -121,7 +149,11 @@ public function getTestCases() 'maximalPrice' => 65 ] ], - '#8 Testing product price with tier price and sub items Configuration #8' => [ + + ' + #8 Testing product price for dynamic bundle + with two non required options and tier price + ' => [ 'strategy' => $this->getBundleConfiguration8(), 'expectedResults' => [ // 0.5 * (1 * 10) @@ -130,8 +162,12 @@ public function getTestCases() 'maximalPrice' => 65 ] ], - '#9 Testing price for dynamic bundle product with tier price on it and on sub item' => [ - 'strategy' => $this->getBundleConfiguration10(), + + ' + #9 Testing product price for dynamic bundle + with tier price and with simple with tier price + ' => [ + 'strategy' => $this->getBundleConfiguration9(), 'expectedResults' => [ // 0.5 * 1 * 2.5 'minimalPrice' => 1.25, @@ -142,6 +178,10 @@ public function getTestCases() ]; } + /** + * Dynamic bundle with one required option and tier price + * @return array + */ private function getBundleConfiguration1() { $optionsData = [ @@ -176,6 +216,10 @@ private function getBundleConfiguration1() ]; } + /** + * Dynamic bundle with one non required option and tier price + * @return array + */ private function getBundleConfiguration2() { $optionsData = [ @@ -210,6 +254,10 @@ private function getBundleConfiguration2() ]; } + /** + * Dynamic bundle with one required checkbox type option and tier price + * @return array + */ private function getBundleConfiguration3() { $optionsData = [ @@ -248,6 +296,10 @@ private function getBundleConfiguration3() ]; } + /** + * Dynamic bundle with one required multi type option and tier price + * @return array + */ private function getBundleConfiguration4() { $optionsData = [ @@ -286,6 +338,10 @@ private function getBundleConfiguration4() ]; } + /** + * Dynamic bundle with one required radio type option and tier price + * @return array + */ private function getBundleConfiguration5() { $optionsData = [ @@ -324,6 +380,10 @@ private function getBundleConfiguration5() ]; } + /** + * Dynamic bundle with two required options and tier price + * @return array + */ private function getBundleConfiguration6() { $optionsData = [ @@ -377,6 +437,10 @@ private function getBundleConfiguration6() ]; } + /** + * Dynamic bundle with one required option, one non required option and tier price + * @return array + */ private function getBundleConfiguration7() { $optionsData = [ @@ -430,6 +494,10 @@ private function getBundleConfiguration7() ]; } + /** + * Dynamic bundle with two non required options and tier price + * @return array + */ private function getBundleConfiguration8() { $optionsData = [ @@ -483,7 +551,11 @@ private function getBundleConfiguration8() ]; } - private function getBundleConfiguration10() + /** + * Dynamic bundle with tier price and with simple with tier price + * @return array + */ + private function getBundleConfiguration9() { $optionsData = [ [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php index faf0bfcfa3396..28e4886fb16ef 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundlePriceCalculatorTest.php @@ -87,7 +87,8 @@ public function getTestCases() 'maximalPrice' => 120 ] ], - '#2 Testing price for fixed bundle product with three simples and differnt qty' => [ + + '#2 Testing price for fixed bundle product with three simples and different qty' => [ 'strategy' => $this->getProductWithDifferentQty(), 'expectedResults' => [ // 110 + 10 (min price from simples) @@ -96,7 +97,8 @@ public function getTestCases() 'maximalPrice' => 170 ] ], - '#3 Testing price for fixed bundle product with three simples and differnt price' => [ + + '#3 Testing price for fixed bundle product with three simples and different price' => [ 'strategy' => $this->getProductWithDifferentPrice(), 'expectedResults' => [ // 110 + 10 @@ -105,6 +107,7 @@ public function getTestCases() 'maximalPrice' => 170 ] ], + '#4 Testing price for fixed bundle product with three simples' => [ 'strategy' => $this->getProductWithSamePrice(), 'expectedResults' => [ @@ -117,6 +120,10 @@ public function getTestCases() ]; } + /** + * Fixed bundle product with one simple + * @return array + */ private function getProductWithOneSimple() { $optionsData = [ @@ -143,6 +150,10 @@ private function getProductWithOneSimple() ]; } + /** + * Fixed bundle product with three simples and different qty + * @return array + */ private function getProductWithDifferentQty() { $optionsData = [ @@ -181,6 +192,10 @@ private function getProductWithDifferentQty() ]; } + /** + * Fixed bundle product with three simples and different price + * @return array + */ private function getProductWithSamePrice() { $optionsData = [ @@ -219,6 +234,10 @@ private function getProductWithSamePrice() ]; } + /** + * Fixed bundle product with three simples + * @return array + */ private function getProductWithDifferentPrice() { $optionsData = [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php index a18929463ea95..57c8ba0cbbde1 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithCatalogPriceRuleCalculatorTest.php @@ -45,6 +45,7 @@ public function testPriceForFixedBundle(array $strategyModifiers, array $expecte /** * Test cases for current test * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function getTestCases() { @@ -53,7 +54,7 @@ public function getTestCases() #1 Testing price for fixed bundle product with catalog price rule and without sub items and options ' => [ - 'strategy' => $this->getEmptyProductStrategy(), + 'strategy' => $this->getBundleConfiguration1(), 'expectedResults' => [ // 110 * 0.9 'minimalPrice' => 99, @@ -67,7 +68,7 @@ public function getTestCases() #2 Testing price for fixed bundle product with catalog price rule, fixed sub items and fixed options ' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + 'strategy' => $this->getBundleConfiguration2( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -84,7 +85,7 @@ public function getTestCases() #3 Testing price for fixed bundle product with catalog price rule, percent sub items and percent options ' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + 'strategy' => $this->getBundleConfiguration2( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -101,7 +102,7 @@ public function getTestCases() #4 Testing price for fixed bundle product with catalog price rule, fixed sub items and percent options ' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + 'strategy' => $this->getBundleConfiguration2( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -118,7 +119,7 @@ public function getTestCases() #5 Testing price for fixed bundle product with catalog price rule, percent sub items and fixed options ' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + 'strategy' => $this->getBundleConfiguration2( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -133,77 +134,9 @@ public function getTestCases() ' #6 Testing price for fixed bundle product - with catalog price rule, fixed sub items and fixed options Configuration #1 - ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration1( - LinkInterface::PRICE_TYPE_FIXED, - self::CUSTOM_OPTION_PRICE_TYPE_FIXED - ), - 'expectedResults' => [ - // 0.9 * 110 + 1 * 20 + 100 - 'minimalPrice' => 219, - - // 0.9 * 110 + 1 * 20 + 100 - 'maximalPrice' => 219 - ] - ], - - ' - #7 Testing price for fixed bundle product - with catalog price rule, percent sub items and percent options Configuration #1 - ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration1( - LinkInterface::PRICE_TYPE_PERCENT, - self::CUSTOM_OPTION_PRICE_TYPE_PERCENT - ), - 'expectedResults' => [ - // 0.9 * 110 + 0.9 * 110 * 0.2 + 0.9 * 110 * 1 - 'minimalPrice' => 217.8, - - // 0.9 * 110 + 0.9 * 110 * 0.2 + 0.9 * 110 * 1 - 'maximalPrice' => 217.8 - ] - ], - - ' - #8 Testing price for fixed bundle product - with catalog price rule, fixed sub items and percent options Configuration #1 - ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration1( - LinkInterface::PRICE_TYPE_FIXED, - self::CUSTOM_OPTION_PRICE_TYPE_PERCENT - ), - 'expectedResults' => [ - // 0.9 * 110 + 1 * 20 + 0.9 * 110 * 1 - 'minimalPrice' => 218, - - // 0.9 * 110 + 1 * 20 + 0.9 * 110 * 1 - 'maximalPrice' => 218 - ] - ], - - ' - #9 Testing price for fixed bundle product - with catalog price rule, percent sub items and fixed options Configuration #1 - ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration1( - LinkInterface::PRICE_TYPE_PERCENT, - self::CUSTOM_OPTION_PRICE_TYPE_FIXED - ), - 'expectedResults' => [ - // 0.9 * 110 + 0.9 * 110 * 0.2 + 100 - 'minimalPrice' => 218.8, - - // 0.9 * 110 + 0.9 * 110 * 0.2 + 100 - 'maximalPrice' => 218.8 - ] - ], - - ' - #10 Testing price for fixed bundle product - with catalog price rule, fixed sub items and fixed options Configuration #2 + with catalog price rule, fixed sub items and fixed options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration2( + 'strategy' => $this->getBundleConfiguration3( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -217,10 +150,10 @@ public function getTestCases() ], ' - #11 Testing price for fixed bundle product - with catalog price rule, percent sub items and percent options Configuration #2 + #7 Testing price for fixed bundle product + with catalog price rule, percent sub items and percent options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration2( + 'strategy' => $this->getBundleConfiguration3( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -234,10 +167,10 @@ public function getTestCases() ], ' - #12 Testing price for fixed bundle product - with catalog price rule, fixed sub items and percent options Configuration #2 + #8 Testing price for fixed bundle product + with catalog price rule, fixed sub items and percent options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration2( + 'strategy' => $this->getBundleConfiguration3( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -251,10 +184,10 @@ public function getTestCases() ], ' - #13 Testing price for fixed bundle product - with catalog price rule, percent sub items and fixed options Configuration #2 + #9 Testing price for fixed bundle product + with catalog price rule, percent sub items and fixed options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration2( + 'strategy' => $this->getBundleConfiguration3( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -268,10 +201,10 @@ public function getTestCases() ], ' - #14 Testing price for fixed bundle product - with catalog price rule, fixed sub items and fixed options Configuration #3 + #10 Testing price for fixed bundle product + with catalog price rule, fixed sub items and fixed options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration3( + 'strategy' => $this->getBundleConfiguration4( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -285,10 +218,10 @@ public function getTestCases() ], ' - #15 Testing price for fixed bundle product - with catalog price rule, percent sub items and percent options Configuration #3 + #11 Testing price for fixed bundle product + with catalog price rule, percent sub items and percent options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration3( + 'strategy' => $this->getBundleConfiguration4( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -302,10 +235,10 @@ public function getTestCases() ], ' - #16 Testing price for fixed bundle product - with catalog price rule, fixed sub items and percent options Configuration #3 + #12 Testing price for fixed bundle product + with catalog price rule, fixed sub items and percent options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration3( + 'strategy' => $this->getBundleConfiguration4( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -319,10 +252,10 @@ public function getTestCases() ], ' - #17 Testing price for fixed bundle product - with catalog price rule, percent sub items and fixed options Configuration #3 + #13 Testing price for fixed bundle product + with catalog price rule, percent sub items and fixed options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration3( + 'strategy' => $this->getBundleConfiguration4( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -336,10 +269,10 @@ public function getTestCases() ], ' - #18 Testing price for fixed bundle product - with catalog price rule, fixed sub items and fixed options Configuration #4 + #14 Testing price for fixed bundle product + with catalog price rule, fixed sub items and fixed options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration4( + 'strategy' => $this->getBundleConfiguration5( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -353,10 +286,10 @@ public function getTestCases() ], ' - #19 Testing price for fixed bundle product - with catalog price rule, percent sub items and percent options Configuration #4 + #15 Testing price for fixed bundle product + with catalog price rule, percent sub items and percent options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration4( + 'strategy' => $this->getBundleConfiguration5( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -370,10 +303,10 @@ public function getTestCases() ], ' - #20 Testing price for fixed bundle product - with catalog price rule, fixed sub items and percent options Configuration #4 + #16 Testing price for fixed bundle product + with catalog price rule, fixed sub items and percent options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration4( + 'strategy' => $this->getBundleConfiguration5( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -387,10 +320,10 @@ public function getTestCases() ], ' - #21 Testing price for fixed bundle product - with catalog price rule, percent sub items and fixed options Configuration #4 + #17 Testing price for fixed bundle product + with catalog price rule, percent sub items and fixed options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration4( + 'strategy' => $this->getBundleConfiguration5( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -404,10 +337,10 @@ public function getTestCases() ], ' - #22 Testing price for fixed bundle product - with catalog price rule, fixed sub items and fixed options Configuration #5 + #18 Testing price for fixed bundle product + with catalog price rule, fixed sub items and fixed options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration5( + 'strategy' => $this->getBundleConfiguration6( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -421,10 +354,10 @@ public function getTestCases() ], ' - #23 Testing price for fixed bundle product - with catalog price rule, percent sub items and percent options Configuration #5 + #19 Testing price for fixed bundle product + with catalog price rule, percent sub items and percent options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration5( + 'strategy' => $this->getBundleConfiguration6( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -438,10 +371,10 @@ public function getTestCases() ], ' - #24 Testing price for fixed bundle product - with catalog price rule, fixed sub items and percent options Configuration #5 + #20 Testing price for fixed bundle product + with catalog price rule, fixed sub items and percent options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration5( + 'strategy' => $this->getBundleConfiguration6( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -455,10 +388,10 @@ public function getTestCases() ], ' - #25 Testing price for fixed bundle product - with catalog price rule, percent sub items and fixed options Configuration #5 + #21 Testing price for fixed bundle product + with catalog price rule, percent sub items and fixed options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration5( + 'strategy' => $this->getBundleConfiguration6( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -472,10 +405,10 @@ public function getTestCases() ], ' - #26 Testing price for fixed bundle product - with catalog price rule, fixed sub items and fixed options Configuration #6 + #22 Testing price for fixed bundle product + with catalog price rule, fixed sub items and fixed options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration6( + 'strategy' => $this->getBundleConfiguration7( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -489,10 +422,10 @@ public function getTestCases() ], ' - #27 Testing price for fixed bundle product - with catalog price rule, percent sub items and percent options Configuration #6 + #23 Testing price for fixed bundle product + with catalog price rule, percent sub items and percent options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration6( + 'strategy' => $this->getBundleConfiguration7( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -506,10 +439,10 @@ public function getTestCases() ], ' - #28 Testing price for fixed bundle product - with catalog price rule, fixed sub items and percent options Configuration #6 + #24 Testing price for fixed bundle product + with catalog price rule, fixed sub items and percent options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration6( + 'strategy' => $this->getBundleConfiguration7( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -523,10 +456,10 @@ public function getTestCases() ], ' - #29 Testing price for fixed bundle product - with catalog price rule, percent sub items and fixed options Configuration #6 + #25 Testing price for fixed bundle product + with catalog price rule, percent sub items and fixed options ' => [ - 'strategy' => $this->getProductSubItemsAndOptionsStrategyConfiguration6( + 'strategy' => $this->getBundleConfiguration7( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -541,53 +474,22 @@ public function getTestCases() ]; } - private function getEmptyProductStrategy() + /** + * Fixed bundle product with catalog price rule and without sub items and options + * @return array + */ + private function getBundleConfiguration1() { return []; } - private function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $customOptionsPriceType) - { - $optionsData = [ - [ - 'title' => 'Op1', - 'required' => true, - 'type' => 'checkbox', - 'links' => [ - [ - 'sku' => 'simple1', - 'qty' => 1, - 'price' => 20, - 'price_type' => $selectionsPriceType - ], - ] - ], - ]; - - $customOptionsData = [ - [ - 'price_type' => $customOptionsPriceType, - 'title' => 'Test Field', - 'type' => 'field', - 'is_require' => 1, - 'price' => 100, - 'sku' => '1-text', - ] - ]; - - return [ - [ - 'modifierName' => 'addSimpleProduct', - 'data' => [$optionsData] - ], - [ - 'modifierName' => 'addCustomOption', - 'data' => [$customOptionsData] - ], - ]; - } - - private function getProductSubItemsAndOptionsStrategyConfiguration1($selectionsPriceType, $customOptionsPriceType) + /** + * Fixed bundle product with catalog price rule, one required option and one custom option + * @param string $selectionsPriceType + * @param string $customOptionsPriceType + * @return array + */ + private function getBundleConfiguration2($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -628,7 +530,13 @@ private function getProductSubItemsAndOptionsStrategyConfiguration1($selectionsP ]; } - private function getProductSubItemsAndOptionsStrategyConfiguration2($selectionsPriceType, $customOptionsPriceType) + /** + * Fixed bundle product with catalog price rule, one non required option and one custom option + * @param string $selectionsPriceType + * @param string $customOptionsPriceType + * @return array + */ + private function getBundleConfiguration3($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -669,7 +577,13 @@ private function getProductSubItemsAndOptionsStrategyConfiguration2($selectionsP ]; } - private function getProductSubItemsAndOptionsStrategyConfiguration3($selectionsPriceType, $customOptionsPriceType) + /** + * Fixed bundle product with catalog price rule, one checkbox type option with 2 simples and one custom option + * @param string $selectionsPriceType + * @param string $customOptionsPriceType + * @return array + */ + private function getBundleConfiguration4($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -716,7 +630,13 @@ private function getProductSubItemsAndOptionsStrategyConfiguration3($selectionsP ]; } - private function getProductSubItemsAndOptionsStrategyConfiguration4($selectionsPriceType, $customOptionsPriceType) + /** + * Fixed bundle product with catalog price rule, one multi type option with 2 simples and one custom option + * @param string $selectionsPriceType + * @param string $customOptionsPriceType + * @return array + */ + private function getBundleConfiguration5($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -763,7 +683,13 @@ private function getProductSubItemsAndOptionsStrategyConfiguration4($selectionsP ]; } - private function getProductSubItemsAndOptionsStrategyConfiguration5($selectionsPriceType, $customOptionsPriceType) + /** + * Fixed bundle product with catalog price rule, one radio type option with 2 simples and one custom option + * @param string $selectionsPriceType + * @param string $customOptionsPriceType + * @return array + */ + private function getBundleConfiguration6($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -810,7 +736,13 @@ private function getProductSubItemsAndOptionsStrategyConfiguration5($selectionsP ]; } - private function getProductSubItemsAndOptionsStrategyConfiguration6($selectionsPriceType, $customOptionsPriceType) + /** + * Fixed bundle product with catalog price rule, two required options and one custom option + * @param string $selectionsPriceType + * @param string $customOptionsPriceType + * @return array + */ + private function getBundleConfiguration7($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php index 092c35fc5db3c..55fe57d082639 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithSpecialPriceCalculatorTest.php @@ -45,6 +45,7 @@ public function testPriceForFixedBundle(array $strategyModifiers, array $expecte /** * Test cases for current test * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function getTestCases() { @@ -53,7 +54,7 @@ public function getTestCases() #1 Testing price for fixed bundle product without any discounts, sub items and options ' => [ - 'strategy' => $this->getEmptyProductStrategy(), + 'strategy' => $this->getBundleConfiguration1(), 'expectedResults' => [ // just product price 'minimalPrice' => 110, @@ -67,7 +68,7 @@ public function getTestCases() #2 Testing price for fixed bundle product with special price and without any sub items and options ' => [ - 'strategy' => $this->getEmptyProductWithSpecialPriceStrategy(), + 'strategy' => $this->getBundleConfiguration2(), 'expectedResults' => [ // 110 * 0.5 'minimalPrice' => 55, @@ -81,7 +82,7 @@ public function getTestCases() #3 Testing price for fixed bundle product with fixed sub items, fixed options and without any discounts ' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + 'strategy' => $this->getBundleConfiguration3( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -98,7 +99,7 @@ public function getTestCases() #4 Testing price for fixed bundle product with percent sub items, percent options and without any discounts ' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + 'strategy' => $this->getBundleConfiguration3( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -115,7 +116,7 @@ public function getTestCases() #5 Testing price for fixed bundle product with fixed sub items, percent options and without any discounts ' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + 'strategy' => $this->getBundleConfiguration3( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -132,7 +133,7 @@ public function getTestCases() #6 Testing price for fixed bundle product with percent sub items, fixed options and without any discounts ' => [ - 'strategy' => $this->getProductWithSubItemsAndOptionsStrategy( + 'strategy' => $this->getBundleConfiguration3( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -147,9 +148,9 @@ public function getTestCases() ' #7 Testing price for fixed bundle product - with special price, fixed sub items and fixed options Configuration #1 + with special price, fixed sub items and fixed options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + 'strategy' => $this->getBundleConfiguration4( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -164,9 +165,9 @@ public function getTestCases() ' #8 Testing price for fixed bundle product - with special price, percent sub items and percent options Configuration #1 + with special price, percent sub items and percent options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + 'strategy' => $this->getBundleConfiguration4( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -181,9 +182,9 @@ public function getTestCases() ' #9 Testing price for fixed bundle product - with special price, fixed sub items and percent options Configuration #1 + with special price, fixed sub items and percent options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + 'strategy' => $this->getBundleConfiguration4( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -198,9 +199,9 @@ public function getTestCases() ' #10 Testing price for fixed bundle product - with special price, percent sub items and fixed options Configuration #1 + with special price, percent sub items and fixed options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + 'strategy' => $this->getBundleConfiguration4( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -215,9 +216,9 @@ public function getTestCases() ' #11 Testing price for fixed bundle product - with special price, fixed sub items and fixed options Configuration #2 + with special price, fixed sub items and fixed options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + 'strategy' => $this->getBundleConfiguration5( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -232,9 +233,9 @@ public function getTestCases() ' #12 Testing price for fixed bundle product - with special price, percent sub items and percent options Configuration #2 + with special price, percent sub items and percent options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + 'strategy' => $this->getBundleConfiguration5( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -249,9 +250,9 @@ public function getTestCases() ' #13 Testing price for fixed bundle product - with special price, fixed sub items and percent options Configuration #2 + with special price, fixed sub items and percent options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + 'strategy' => $this->getBundleConfiguration5( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -266,9 +267,9 @@ public function getTestCases() ' #14 Testing price for fixed bundle product - with special price, percent sub items and fixed options Configuration #2 + with special price, percent sub items and fixed options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + 'strategy' => $this->getBundleConfiguration5( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -283,9 +284,9 @@ public function getTestCases() ' #15 Testing price for fixed bundle product - with special price, fixed sub items and fixed options Configuration #3 + with special price, fixed sub items and fixed options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + 'strategy' => $this->getBundleConfiguration6( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -300,9 +301,9 @@ public function getTestCases() ' #16 Testing price for fixed bundle product - with special price, percent sub items and percent options Configuration #3 + with special price, percent sub items and percent options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + 'strategy' => $this->getBundleConfiguration6( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -317,9 +318,9 @@ public function getTestCases() ' #17 Testing price for fixed bundle product - with special price, fixed sub items and percent options Configuration #3 + with special price, fixed sub items and percent options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + 'strategy' => $this->getBundleConfiguration6( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -334,9 +335,9 @@ public function getTestCases() ' #18 Testing price for fixed bundle product - with special price, percent sub items and fixed options Configuration #3 + with special price, percent sub items and fixed options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + 'strategy' => $this->getBundleConfiguration6( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -351,9 +352,9 @@ public function getTestCases() ' #19 Testing price for fixed bundle product - with special price, fixed sub items and fixed options Configuration #4 + with special price, fixed sub items and fixed options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + 'strategy' => $this->getBundleConfiguration7( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -368,9 +369,9 @@ public function getTestCases() ' #20 Testing price for fixed bundle product - with special price, percent sub items and percent options Configuration #4 + with special price, percent sub items and percent options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + 'strategy' => $this->getBundleConfiguration7( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -385,9 +386,9 @@ public function getTestCases() ' #21 Testing price for fixed bundle product - with special price, fixed sub items and percent options Configuration #4 + with special price, fixed sub items and percent options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + 'strategy' => $this->getBundleConfiguration7( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -402,9 +403,9 @@ public function getTestCases() ' #22 Testing price for fixed bundle product - with special price, percent sub items and fixed options Configuration #4 + with special price, percent sub items and fixed options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + 'strategy' => $this->getBundleConfiguration7( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -419,9 +420,9 @@ public function getTestCases() ' #23 Testing price for fixed bundle product - with special price, fixed sub items and fixed options Configuration #5 + with special price, fixed sub items and fixed options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + 'strategy' => $this->getBundleConfiguration8( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -436,9 +437,9 @@ public function getTestCases() ' #24 Testing price for fixed bundle product - with special price, percent sub items and percent options Configuration #5 + with special price, percent sub items and percent options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + 'strategy' => $this->getBundleConfiguration8( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -453,9 +454,9 @@ public function getTestCases() ' #25 Testing price for fixed bundle product - with special price, fixed sub items and percent options Configuration #5 + with special price, fixed sub items and percent options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + 'strategy' => $this->getBundleConfiguration8( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -470,9 +471,9 @@ public function getTestCases() ' #26 Testing price for fixed bundle product - with special price, percent sub items and fixed options Configuration #5 + with special price, percent sub items and fixed options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + 'strategy' => $this->getBundleConfiguration8( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -487,9 +488,9 @@ public function getTestCases() ' #27 Testing price for fixed bundle product - with special price, fixed sub items and fixed options Configuration #6 + with special price, fixed sub items and fixed options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + 'strategy' => $this->getBundleConfiguration9( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -504,9 +505,9 @@ public function getTestCases() ' #28 Testing price for fixed bundle product - with special price, percent sub items and percent options Configuration #6 + with special price, percent sub items and percent options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + 'strategy' => $this->getBundleConfiguration9( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -521,9 +522,9 @@ public function getTestCases() ' #29 Testing price for fixed bundle product - with special price, fixed sub items and percent options Configuration #6 + with special price, fixed sub items and percent options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + 'strategy' => $this->getBundleConfiguration9( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -538,9 +539,9 @@ public function getTestCases() ' #30 Testing price for fixed bundle product - with special price, percent sub items and fixed options Configuration #6 + with special price, percent sub items and fixed options ' => [ - 'strategy' => $this->getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + 'strategy' => $this->getBundleConfiguration9( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -555,12 +556,20 @@ public function getTestCases() ]; } - private function getEmptyProductStrategy() + /** + * Fixed bundle product without any discounts, sub items and options + * @return array + */ + private function getBundleConfiguration1() { return []; } - private function getEmptyProductWithSpecialPriceStrategy() + /** + * Fixed bundle product with special price and without any sub items and options + * @return array + */ + private function getBundleConfiguration2() { return [ [ @@ -570,7 +579,13 @@ private function getEmptyProductWithSpecialPriceStrategy() ]; } - private function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, $customOptionsPriceType) + /** + * Fixed bundle product with required option, custom option and without any discounts + * @param $selectionsPriceType + * @param $customOptionsPriceType + * @return array + */ + private function getBundleConfiguration3($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -611,7 +626,13 @@ private function getProductWithSubItemsAndOptionsStrategy($selectionsPriceType, ]; } - private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration1( + /** + * Fixed bundle product with required option, custom option and with special price + * @param $selectionsPriceType + * @param $customOptionsPriceType + * @return array + */ + private function getBundleConfiguration4( $selectionsPriceType, $customOptionsPriceType ) { @@ -658,7 +679,13 @@ private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfigurati ]; } - private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration2( + /** + * Fixed bundle product with non required option, custom option and with special price + * @param $selectionsPriceType + * @param $customOptionsPriceType + * @return array + */ + private function getBundleConfiguration5( $selectionsPriceType, $customOptionsPriceType ) { @@ -705,7 +732,13 @@ private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfigurati ]; } - private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration3( + /** + * Fixed bundle product with checkbox type option, custom option and with special price + * @param $selectionsPriceType + * @param $customOptionsPriceType + * @return array + */ + private function getBundleConfiguration6( $selectionsPriceType, $customOptionsPriceType ) { @@ -758,7 +791,13 @@ private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfigurati ]; } - private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration4( + /** + * Fixed bundle product with multi type option, custom option and with special price + * @param $selectionsPriceType + * @param $customOptionsPriceType + * @return array + */ + private function getBundleConfiguration7( $selectionsPriceType, $customOptionsPriceType ) { @@ -811,7 +850,13 @@ private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfigurati ]; } - private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration5( + /** + * Fixed bundle product with radio type option, custom option and with special price + * @param $selectionsPriceType + * @param $customOptionsPriceType + * @return array + */ + private function getBundleConfiguration8( $selectionsPriceType, $customOptionsPriceType ) { @@ -864,7 +909,13 @@ private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfigurati ]; } - private function getProductWithSpecialPriceSubItemsAndOptionsStrategyConfiguration6( + /** + * Fixed bundle product with two required options, custom option and with special price + * @param $selectionsPriceType + * @param $customOptionsPriceType + * @return array + */ + private function getBundleConfiguration9( $selectionsPriceType, $customOptionsPriceType ) { diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php index 7766158967f55..bd148080631ae 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php @@ -57,13 +57,16 @@ public function testPriceForFixedBundle(array $strategyModifiers, array $expecte /** * Test cases for current test * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function getTestCases() { - return [ - '#1 Testing product price with tier price and without any sub items and options' => [ - 'strategy' => $this->getEmptyProduct(), + ' + #1 Testing product price + with tier price and without any sub items and options + ' => [ + 'strategy' => $this->getBundleConfiguration1(), 'expectedResults' => [ // 110 * 0.5 'minimalPrice' => 55, @@ -73,8 +76,11 @@ public function getTestCases() ] ], - '#2 Testing product price with tier price, fixed sub items and fixed options Configuration #1' => [ - 'strategy' => $this->getProductConfiguration1( + ' + #2 Testing product price + with tier price, fixed sub items and fixed options + ' => [ + 'strategy' => $this->getProductConfiguration2( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -87,8 +93,11 @@ public function getTestCases() ] ], - '#3 Testing product price with tier price, percent sub items and percent options Configuration #1' => [ - 'strategy' => $this->getProductConfiguration1( + ' + #3 Testing product price + with tier price, percent sub items and percent options + ' => [ + 'strategy' => $this->getProductConfiguration2( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -101,8 +110,11 @@ public function getTestCases() ] ], - '#4 Testing product price with tier price, fixed sub items and percent options Configuration #1' => [ - 'strategy' => $this->getProductConfiguration1( + ' + #4 Testing product price + with tier price, fixed sub items and percent options + ' => [ + 'strategy' => $this->getProductConfiguration2( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -115,8 +127,11 @@ public function getTestCases() ] ], - '#5 Testing product price with tier price, percent sub items and fixed options Configuration #1' => [ - 'strategy' => $this->getProductConfiguration1( + ' + #5 Testing product price + with tier price, percent sub items and fixed options + ' => [ + 'strategy' => $this->getProductConfiguration2( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -129,8 +144,11 @@ public function getTestCases() ] ], - '#6 Testing product price with tier price, fixed sub items and fixed options Configuration #2' => [ - 'strategy' => $this->getProductConfiguration2( + ' + #6 Testing product price + with tier price, fixed sub items and fixed options + ' => [ + 'strategy' => $this->getProductConfiguration3( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -143,8 +161,11 @@ public function getTestCases() ] ], - '#7 Testing product price with tier price, percent sub items and percent options Configuration #2' => [ - 'strategy' => $this->getProductConfiguration2( + ' + #7 Testing product price + with tier price, percent sub items and percent options + ' => [ + 'strategy' => $this->getProductConfiguration3( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -157,8 +178,11 @@ public function getTestCases() ] ], - '#8 Testing product price with tier price, fixed sub items and percent options Configuration #2' => [ - 'strategy' => $this->getProductConfiguration2( + ' + #8 Testing product price + with tier price, fixed sub items and percent options + ' => [ + 'strategy' => $this->getProductConfiguration3( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -171,8 +195,11 @@ public function getTestCases() ] ], - '#9 Testing product price with tier price, percent sub items and fixed options Configuration #2' => [ - 'strategy' => $this->getProductConfiguration2( + ' + #9 Testing product price + with tier price, percent sub items and fixed options + ' => [ + 'strategy' => $this->getProductConfiguration3( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -185,8 +212,11 @@ public function getTestCases() ] ], - '#10 Testing product price with tier price, fixed sub items and fixed options Configuration #3' => [ - 'strategy' => $this->getProductConfiguration3( + ' + #10 Testing product price + with tier price, fixed sub items and fixed options + ' => [ + 'strategy' => $this->getProductConfiguration4( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -199,8 +229,11 @@ public function getTestCases() ] ], - '#11 Testing product price with tier price, percent sub items and percent options Configuration #3' => [ - 'strategy' => $this->getProductConfiguration3( + ' + #11 Testing product price + with tier price, percent sub items and percent options + ' => [ + 'strategy' => $this->getProductConfiguration4( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -213,8 +246,11 @@ public function getTestCases() ] ], - '#12 Testing product price with tier price, fixed sub items and percent options Configuration #3' => [ - 'strategy' => $this->getProductConfiguration3( + ' + #12 Testing product price + with tier price, fixed sub items and percent options + ' => [ + 'strategy' => $this->getProductConfiguration4( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -227,8 +263,11 @@ public function getTestCases() ] ], - '#13 Testing product price with tier price, percent sub items and fixed options Configuration #3' => [ - 'strategy' => $this->getProductConfiguration3( + ' + #13 Testing product price + with tier price, percent sub items and fixed options + ' => [ + 'strategy' => $this->getProductConfiguration4( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -241,8 +280,11 @@ public function getTestCases() ] ], - '#14 Testing product price with tier price, fixed sub items and fixed options Configuration #4' => [ - 'strategy' => $this->getProductConfiguration4( + ' + #14 Testing product price + with tier price, fixed sub items and fixed options + ' => [ + 'strategy' => $this->getProductConfiguration5( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -255,8 +297,11 @@ public function getTestCases() ] ], - '#15 Testing product price with tier price, percent sub items and percent options Configuration #4' => [ - 'strategy' => $this->getProductConfiguration4( + ' + #15 Testing product price + with tier price, percent sub items and percent options + ' => [ + 'strategy' => $this->getProductConfiguration5( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -269,8 +314,11 @@ public function getTestCases() ] ], - '#16 Testing product price with tier price, fixed sub items and percent options Configuration #4' => [ - 'strategy' => $this->getProductConfiguration4( + ' + #16 Testing product price + with tier price, fixed sub items and percent options + ' => [ + 'strategy' => $this->getProductConfiguration5( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -283,8 +331,11 @@ public function getTestCases() ] ], - '#17 Testing product price with tier price, percent sub items and fixed options Configuration #4' => [ - 'strategy' => $this->getProductConfiguration4( + ' + #17 Testing product price + with tier price, percent sub items and fixed options + ' => [ + 'strategy' => $this->getProductConfiguration5( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -297,8 +348,11 @@ public function getTestCases() ] ], - '#18 Testing product price with tier price, fixed sub items and fixed options Configuration #5' => [ - 'strategy' => $this->getProductConfiguration5( + ' + #18 Testing product price + with tier price, fixed sub items and fixed options + ' => [ + 'strategy' => $this->getProductConfiguration6( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -311,8 +365,11 @@ public function getTestCases() ] ], - '#19 Testing product price with tier price, percent sub items and percent options Configuration #5' => [ - 'strategy' => $this->getProductConfiguration5( + ' + #19 Testing product price + with tier price, percent sub items and percent options + ' => [ + 'strategy' => $this->getProductConfiguration6( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -325,8 +382,11 @@ public function getTestCases() ] ], - '#20 Testing product price with tier price, fixed sub items and percent options Configuration #5' => [ - 'strategy' => $this->getProductConfiguration5( + ' + #20 Testing product price + with tier price, fixed sub items and percent options + ' => [ + 'strategy' => $this->getProductConfiguration6( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -339,8 +399,11 @@ public function getTestCases() ] ], - '#21 Testing product price with tier price, percent sub items and fixed options Configuration #5' => [ - 'strategy' => $this->getProductConfiguration5( + ' + #21 Testing product price + with tier price, percent sub items and fixed options + ' => [ + 'strategy' => $this->getProductConfiguration6( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -353,8 +416,11 @@ public function getTestCases() ] ], - '#22 Testing product price with tier price, fixed sub items and fixed options Configuration #6' => [ - 'strategy' => $this->getProductConfiguration6( + ' + #22 Testing product price + with tier price, fixed sub items and fixed options + ' => [ + 'strategy' => $this->getProductConfiguration7( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -367,8 +433,11 @@ public function getTestCases() ] ], - '#23 Testing product price with tier price, percent sub items and percent options Configuration #6' => [ - 'strategy' => $this->getProductConfiguration6( + ' + #23 Testing product price + with tier price, percent sub items and percent options + ' => [ + 'strategy' => $this->getProductConfiguration7( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -381,8 +450,11 @@ public function getTestCases() ] ], - '#24 Testing product price with tier price, fixed sub items and percent options Configuration #6' => [ - 'strategy' => $this->getProductConfiguration6( + ' + #24 Testing product price + with tier price, fixed sub items and percent options + ' => [ + 'strategy' => $this->getProductConfiguration7( LinkInterface::PRICE_TYPE_FIXED, self::CUSTOM_OPTION_PRICE_TYPE_PERCENT ), @@ -395,8 +467,11 @@ public function getTestCases() ] ], - '#25 Testing product price with tier price, percent sub items and fixed options Configuration #6' => [ - 'strategy' => $this->getProductConfiguration6( + ' + #25 Testing product price + with tier price, percent sub items and fixed options + ' => [ + 'strategy' => $this->getProductConfiguration7( LinkInterface::PRICE_TYPE_PERCENT, self::CUSTOM_OPTION_PRICE_TYPE_FIXED ), @@ -408,11 +483,14 @@ public function getTestCases() 'maximalPrice' => 207.25 ] ], - ]; } - private function getEmptyProduct() + /** + * Fixed bundle product without sub items and options and with tier price + * @return array + */ + private function getBundleConfiguration1() { $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, @@ -428,7 +506,13 @@ private function getEmptyProduct() ]; } - private function getProductConfiguration1($selectionsPriceType, $customOptionsPriceType) + /** + * Fixed bundle product with required option, custom option and with tier price + * @param $selectionsPriceType + * @param $customOptionsPriceType + * @return array + */ + private function getProductConfiguration2($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -479,7 +563,13 @@ private function getProductConfiguration1($selectionsPriceType, $customOptionsPr ]; } - private function getProductConfiguration2($selectionsPriceType, $customOptionsPriceType) + /** + * Fixed bundle product with non required option, custom option and with tier price + * @param $selectionsPriceType + * @param $customOptionsPriceType + * @return array + */ + private function getProductConfiguration3($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -530,7 +620,13 @@ private function getProductConfiguration2($selectionsPriceType, $customOptionsPr ]; } - private function getProductConfiguration3($selectionsPriceType, $customOptionsPriceType) + /** + * Fixed bundle product with checkbox type option, custom option and with tier price + * @param $selectionsPriceType + * @param $customOptionsPriceType + * @return array + */ + private function getProductConfiguration4($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -587,7 +683,13 @@ private function getProductConfiguration3($selectionsPriceType, $customOptionsPr ]; } - private function getProductConfiguration4($selectionsPriceType, $customOptionsPriceType) + /** + * Fixed bundle product with multi type option, custom option and with tier price + * @param $selectionsPriceType + * @param $customOptionsPriceType + * @return array + */ + private function getProductConfiguration5($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -644,7 +746,13 @@ private function getProductConfiguration4($selectionsPriceType, $customOptionsPr ]; } - private function getProductConfiguration5($selectionsPriceType, $customOptionsPriceType) + /** + * Fixed bundle product with radio type option, custom option and with tier price + * @param $selectionsPriceType + * @param $customOptionsPriceType + * @return array + */ + private function getProductConfiguration6($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ @@ -701,7 +809,13 @@ private function getProductConfiguration5($selectionsPriceType, $customOptionsPr ]; } - private function getProductConfiguration6($selectionsPriceType, $customOptionsPriceType) + /** + * Fixed bundle product with two required options, custom option and with tier price + * @param $selectionsPriceType + * @param $customOptionsPriceType + * @return array + */ + private function getProductConfiguration7($selectionsPriceType, $customOptionsPriceType) { $optionsData = [ [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php index de45c9e06b447..7882475314072 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php @@ -30,7 +30,7 @@ protected function setUp() } /** - * check bundle product is saleable if his status is enabled + * Check bundle product is saleable if his status is enabled * * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable @@ -48,7 +48,7 @@ public function testIsSaleableOnEnabledStatus() } /** - * check bundle product is NOT saleable if his status is disabled + * Check bundle product is NOT saleable if his status is disabled * * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable @@ -66,7 +66,7 @@ public function testIsSaleableOnDisabledStatus() } /** - * check bundle product is saleable if his status is enabled + * Check bundle product is saleable if his status is enabled * and it has internal data is_salable = true * * @magentoAppIsolation enabled @@ -86,7 +86,7 @@ public function testIsSaleableOnEnabledStatusAndIsSalableIsTrue() } /** - * check bundle product is NOT saleable if + * Check bundle product is NOT saleable if * his status is enabled but his data is_salable = false * * @magentoAppIsolation enabled @@ -106,7 +106,7 @@ public function testIsSaleableOnEnabledStatusAndIsSalableIsFalse() } /** - * check bundle product is saleable if it has all_items_salable = true + * Check bundle product is saleable if it has all_items_salable = true * * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable @@ -124,7 +124,7 @@ public function testIsSaleableOnAllItemsSalableIsTrue() } /** - * check bundle product is NOT saleable if it has all_items_salable = false + * Check bundle product is NOT saleable if it has all_items_salable = false * * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable @@ -142,7 +142,7 @@ public function testIsSaleableOnAllItemsSalableIsFalse() } /** - * check bundle product is NOT saleable if it has no options + * Check bundle product is NOT saleable if it has no options * * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable @@ -170,7 +170,7 @@ public function testIsSaleableOnBundleWithoutOptions() } /** - * check bundle product is NOT saleable if it has no selections + * Check bundle product is NOT saleable if it has no selections * * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable @@ -200,7 +200,7 @@ public function testIsSaleableOnBundleWithoutSelections() } /** - * check bundle product is NOT saleable if + * Check bundle product is NOT saleable if * all his selections are not saleable * * @magentoAppIsolation enabled @@ -225,7 +225,7 @@ public function testIsSaleableOnBundleWithoutSaleableSelections() } /** - * check bundle product is NOT saleable if + * Check bundle product is NOT saleable if * it has at least one required option without saleable selections * * @magentoAppIsolation enabled @@ -250,7 +250,7 @@ public function testIsSaleableOnBundleWithoutSaleableSelectionsOnRequiredOption( } /** - * check bundle product is NOT saleable if + * Check bundle product is NOT saleable if * there are not enough qty of selection on required option * * @magentoAppIsolation enabled @@ -270,7 +270,7 @@ public function testIsSaleableOnBundleWithNotEnoughQtyOfSelection() } /** - * check bundle product is saleable if + * Check bundle product is saleable if * all his selections have selection_can_change_qty = 1 * * @magentoAppIsolation enabled @@ -305,7 +305,7 @@ public function testIsSaleableOnBundleWithSelectionCanChangeQty() } /** - * check bundle product is not saleable if + * Check bundle product is not saleable if * all his options are not required and selections are not saleable * * @magentoAppIsolation enabled @@ -342,7 +342,7 @@ public function testIsSaleableOnBundleWithoutRequiredOptions() } /** - * check bundle product is saleable if + * Check bundle product is saleable if * it has at least one not required option with saleable selections * * @magentoAppIsolation enabled From aa5d9e6e86b38d250c50d0d0719aef10bf15dd76 Mon Sep 17 00:00:00 2001 From: Ievgen Shakhsuvarov Date: Wed, 2 Nov 2016 16:46:04 +0200 Subject: [PATCH 046/161] MAGETWO-59116: Stabilize builds - MAGETWO-55729 [Customer] Optimize performance for bundled products with lots of product options - Unit test fixes --- .../Catalog/Product/View/Type/BundleTest.php | 57 +++++++++++++------ 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php b/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php index f11fc30f5b28f..72cb634127404 100644 --- a/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php @@ -3,26 +3,28 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - namespace Magento\Bundle\Test\Unit\Block\Catalog\Product\View\Type; use Magento\Bundle\Block\Catalog\Product\View\Type\Bundle as BundleBlock; -use Magento\Framework\DataObject as MagentoObject; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class BundleTest extends \PHPUnit_Framework_TestCase { - /** @var \Magento\Bundle\Model\Product\PriceFactory|\PHPUnit_Framework_MockObject_MockObject */ + /** + * @var \Magento\Bundle\Model\Product\PriceFactory|\PHPUnit_Framework_MockObject_MockObject + */ private $bundleProductPriceFactory; - /** @var \Magento\Framework\Json\Encoder|\PHPUnit_Framework_MockObject_MockObject */ + /** + * @var \Magento\Framework\Json\Encoder|\PHPUnit_Framework_MockObject_MockObject + */ private $jsonEncoder; - /** @var \Magento\Catalog\Helper\Product|\PHPUnit_Framework_MockObject_MockObject */ + /** + * @var \Magento\Catalog\Helper\Product|\PHPUnit_Framework_MockObject_MockObject + */ private $catalogProduct; /** @@ -30,7 +32,9 @@ class BundleTest extends \PHPUnit_Framework_TestCase */ private $eventManager; - /** @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject */ + /** + * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject + */ private $product; /** @@ -86,6 +90,15 @@ protected function setUp() 'catalogProduct' => $this->catalogProduct ] ); + + $ruleProcessor = $this->getMockBuilder(\Magento\CatalogRule\Model\ResourceModel\Product\Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $objectHelper->setBackwardCompatibleProperty( + $this->bundleBlock, + 'catalogRuleProcessor', + $ruleProcessor + ); } public function testGetOptionHtmlNoRenderer() @@ -138,7 +151,7 @@ public function testGetJsonConfigFixedPriceBundleNoOption() $options = []; $finalPriceMock = $this->getPriceMock( [ - 'getPriceWithoutOption' => new MagentoObject( + 'getPriceWithoutOption' => new \Magento\Framework\DataObject( [ 'value' => 100, 'base_amount' => 100, @@ -148,7 +161,7 @@ public function testGetJsonConfigFixedPriceBundleNoOption() ); $regularPriceMock = $this->getPriceMock( [ - 'getAmount' => new MagentoObject( + 'getAmount' => new \Magento\Framework\DataObject( [ 'value' => 110, 'base_amount' => 110, @@ -183,7 +196,9 @@ public function testGetJsonConfigFixedPriceBundle() 'Selection 1', 23, [ - ['price' => new MagentoObject(['base_amount' => $baseAmount, 'value' => $basePriceValue])] + ['price' => new \Magento\Framework\DataObject( + ['base_amount' => $baseAmount, 'value' => $basePriceValue] + )] ], true, true @@ -211,7 +226,7 @@ public function testGetJsonConfigFixedPriceBundle() ]; $finalPriceMock = $this->getPriceMock( [ - 'getPriceWithoutOption' => new MagentoObject( + 'getPriceWithoutOption' => new \Magento\Framework\DataObject( [ 'value' => 100, 'base_amount' => 100, @@ -221,7 +236,7 @@ public function testGetJsonConfigFixedPriceBundle() ); $regularPriceMock = $this->getPriceMock( [ - 'getAmount' => new MagentoObject( + 'getAmount' => new \Magento\Framework\DataObject( [ 'value' => 110, 'base_amount' => 110, @@ -269,7 +284,7 @@ public function testGetJsonConfigFixedPriceBundle() * @param array $options * @param \Magento\Framework\Pricing\PriceInfo\Base|\PHPUnit_Framework_MockObject_MockObject $priceInfo * @param string $priceType - * @return BundleBlock + * @return void */ private function updateBundleBlock($options, $priceInfo, $priceType) { @@ -281,6 +296,11 @@ private function updateBundleBlock($options, $priceInfo, $priceType) ->method('appendSelections') ->willReturn($options); + $selectionCollection = $this->getMockBuilder(\Magento\Bundle\Model\ResourceModel\Selection\Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $selectionCollection->expects($this->once())->method('addTierPriceData'); + $typeInstance = $this->getMockBuilder(\Magento\Bundle\Model\Product\Type::class) ->disableOriginalConstructor() ->getMock(); @@ -290,6 +310,9 @@ private function updateBundleBlock($options, $priceInfo, $priceType) $typeInstance->expects($this->any()) ->method('getStoreFilter') ->willReturn(true); + $typeInstance->expects($this->once()) + ->method('getSelectionsCollection') + ->willReturn($selectionCollection); $this->product->expects($this->any()) ->method('getTypeInstance') @@ -368,7 +391,7 @@ private function getAmountPriceMock($value, $baseAmount, array $selectionAmounts ->with($selectionAmount['item']) ->will( $this->returnValue( - new MagentoObject( + new \Magento\Framework\DataObject( [ 'value' => $selectionAmount['value'], 'base_amount' => $selectionAmount['base_amount'], @@ -486,8 +509,8 @@ public function testGetOptions($stripSelection) ->willReturn($optionCollection); $typeInstance->expects($this->any())->method('getStoreFilter')->willReturn(true); $typeInstance->expects($this->any())->method('getOptionsCollection')->willReturn($optionCollection); - $typeInstance->expects($this->any())->method('getOptionsIds')->willReturn([1,2]); - $typeInstance->expects($this->once())->method('getSelectionsCollection')->with([1,2], $this->product) + $typeInstance->expects($this->any())->method('getOptionsIds')->willReturn([1, 2]); + $typeInstance->expects($this->once())->method('getSelectionsCollection')->with([1, 2], $this->product) ->willReturn($selectionConnection); $this->product->expects($this->any()) ->method('getTypeInstance')->willReturn($typeInstance); From 69cf49f6921af44b5036c9cd6a09e53a6fd52e7e Mon Sep 17 00:00:00 2001 From: Ievgen Shakhsuvarov Date: Wed, 2 Nov 2016 17:02:10 +0200 Subject: [PATCH 047/161] MAGETWO-59116: Stabilize builds - MAGETWO-55729 [Customer] Optimize performance for bundled products with lots of product options - Unit test fixes --- .../Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php b/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php index 4c7dc7bdb3ceb..8d9dccfd85f8f 100644 --- a/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php @@ -168,9 +168,10 @@ public function testGetterAmount($amountForBundle, $optionList, $expectedResult) ->getMock(); $selectionsCollection->expects($this->any())->method('getIterator') ->willReturn(new \ArrayIterator($option->getSelections())); + $selectionsCollection->expects($this->atLeastOnce())->method('getFirstItem') + ->willReturn($option->getSelections()[0]); - - $typeInstance->expects($this->at($index + 2))->method('getSelectionsCollection') + $typeInstance->expects($this->atLeastOnce())->method('getSelectionsCollection') ->willReturn($selectionsCollection); } From 00090299cf4964c51ca9337ecea289ec91191e9a Mon Sep 17 00:00:00 2001 From: Ievgen Shakhsuvarov Date: Wed, 2 Nov 2016 17:31:08 +0200 Subject: [PATCH 048/161] MAGETWO-59116: Stabilize builds - MAGETWO-55729 [Customer] Optimize performance for bundled products with lots of product options - Unit test fixes --- .../Magento/Bundle/Test/Unit/Model/Product/TypeTest.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php index dc15017be9d4d..004e717f15680 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php @@ -138,8 +138,6 @@ protected function setUp() ] ); - $objectHelper->setBackwardCompatibleProperty($this->model, 'catalogRuleProcessor', $this->catalogRuleProcessor); - } /** @@ -2096,10 +2094,7 @@ public function testIsSalableFalse() */ public function testIsSalableWithoutOptions() { - $optionCollectionMock = $this->getMockBuilder(\Magento\Bundle\Model\ResourceModel\Option\Collection::class) - ->disableOriginalConstructor() - ->getMock(); - + $optionCollectionMock = $this->getOptionCollectionMock([]); $product = new \Magento\Framework\DataObject( [ 'is_salable' => true, From 2dfec226fa93379c1e12c277943cf3f9ff1cd5ef Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Wed, 2 Nov 2016 18:55:28 +0200 Subject: [PATCH 049/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - removed unnecessary class dependence --- .../Magento/Bundle/Model/Product/BundlePriceAbstract.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePriceAbstract.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePriceAbstract.php index 86bc9f2c80744..e69de8d62ef53 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePriceAbstract.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/BundlePriceAbstract.php @@ -6,8 +6,6 @@ namespace Magento\Bundle\Model\Product; -use Zend\Console\Exception\InvalidArgumentException; - /** * Abstract class for testing bundle prices */ @@ -41,7 +39,6 @@ abstract public function getTestCases(); * @param array $strategyModifiers * @param string $productSku * @return \Magento\Catalog\Api\Data\ProductInterface - * @throws InvalidArgumentException * @throws \Magento\Framework\Exception\NoSuchEntityException * @throws \Magento\Framework\Exception\InputException * @throws \Magento\Framework\Exception\StateException @@ -56,7 +53,7 @@ protected function prepareFixture($strategyModifiers, $productSku) array_unshift($modifier['data'], $bundleProduct); $bundleProduct = call_user_func_array([$this, $modifier['modifierName']], $modifier['data']); } else { - throw new InvalidArgumentException( + throw new \Magento\Framework\Exception\InputException( sprintf('Modifier %s does not exists', $modifier['modifierName']) ); } From 0b46b0e71e6052a4ded63426b1641edc50db7470 Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Wed, 2 Nov 2016 19:40:17 +0200 Subject: [PATCH 050/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - removed unused variable --- .../Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php b/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php index 8d9dccfd85f8f..2d1ac8adce5f2 100644 --- a/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php @@ -162,7 +162,7 @@ public function testGetterAmount($amountForBundle, $optionList, $expectedResult) $optionsCollection->expects($this->atLeastOnce())->method('getSize') ->willReturn(count($options)); - foreach ($options as $index => $option) { + foreach ($options as $option) { $selectionsCollection = $this->getMockBuilder(Collection::class) ->disableOriginalConstructor() ->getMock(); From eebec4f6a1447f68e9777c09210b0e4ef470ea4d Mon Sep 17 00:00:00 2001 From: Iurii Ivashchenko Date: Thu, 3 Nov 2016 12:39:03 +0200 Subject: [PATCH 051/161] MAGETWO-60453: DeleteSavedCreditCardTest fails on bamboo --- .../tests/app/Magento/Payment/Test/Repository/CreditCard.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml index f6c93407a0ccd..b43173f568261 100644 --- a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml +++ b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml @@ -15,7 +15,7 @@ - 378282246310005 + 371449635398431 02 - February 2021 1234 From 398b91532a3abdfd29c9d02749e41ac40b20a611 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Thu, 3 Nov 2016 17:05:23 +0200 Subject: [PATCH 052/161] MAGETWO-60351: Unnecessary disabled payment methods on checkout page #4868 --- .../Plugin/PaymentConfigurationProcess.php | 74 ++++++++ .../PaymentConfigurationProcessTest.php | 131 ++++++++++++++ app/code/Magento/Payment/etc/frontend/di.xml | 3 + .../PaymentVaultConfigurationProcess.php | 92 ++++++++++ .../PaymentVaultConfigurationProcessTest.php | 162 ++++++++++++++++++ app/code/Magento/Vault/etc/frontend/di.xml | 4 + 6 files changed, 466 insertions(+) create mode 100644 app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php create mode 100644 app/code/Magento/Payment/Test/Unit/Plugin/PaymentConfigurationProcessTest.php create mode 100644 app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php create mode 100644 app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultConfigurationProcessTest.php diff --git a/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php b/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php new file mode 100644 index 0000000000000..d618ba92c23f6 --- /dev/null +++ b/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php @@ -0,0 +1,74 @@ +paymentMethodList = $paymentMethodList; + $this->storeManager = $storeManager; + } + + /** + * Checkout LayoutProcessor before process plugin. + * + * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $processor + * @param array $jsLayout + * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforeProcess(\Magento\Checkout\Block\Checkout\LayoutProcessor $processor, $jsLayout) + { + $configuration = &$jsLayout['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children']; + + if (!isset($configuration)) { + return [$jsLayout]; + } + + $storeId = $this->storeManager->getStore()->getId(); + $activePaymentMethodList = $this->paymentMethodList->getActiveList($storeId); + $getCodeFunc = function($method) { + return $method->getCode(); + }; + $activePaymentMethodCodes = array_map($getCodeFunc, $activePaymentMethodList); + + foreach ($configuration as $paymentGroup => $groupConfig) { + foreach (array_keys($groupConfig['methods']) as $paymentCode) { + if (!in_array($paymentCode, $activePaymentMethodCodes)) { + unset($configuration[$paymentGroup]['methods'][$paymentCode]); + } + } + if (empty($configuration[$paymentGroup]['methods'])) { + unset($configuration[$paymentGroup]); + } + } + + return [$jsLayout]; + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Plugin/PaymentConfigurationProcessTest.php b/app/code/Magento/Payment/Test/Unit/Plugin/PaymentConfigurationProcessTest.php new file mode 100644 index 0000000000000..be5755440066e --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Plugin/PaymentConfigurationProcessTest.php @@ -0,0 +1,131 @@ +storeManager = $this + ->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getStore']) + ->getMockForAbstractClass(); + $this->store = $this + ->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getId']) + ->getMockForAbstractClass(); + $this->paymentMethodList = $this + ->getMockBuilder(\Magento\Payment\Api\PaymentMethodListInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getActiveList']) + ->getMockForAbstractClass(); + $this->layoutProcessor = $this + ->getMockBuilder(\Magento\Checkout\Block\Checkout\LayoutProcessor::class) + ->disableOriginalConstructor() + ->setMethods(['process']) + ->getMockForAbstractClass(); + + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->plugin = $objectManagerHelper->getObject( + \Magento\Payment\Plugin\PaymentConfigurationProcess::class, + [ + 'paymentMethodList' => $this->paymentMethodList, + 'storeManager' => $this->storeManager + ] + ); + } + + /** + * @param array $jsLayout + * @param array $activePaymentList + * @param array $expectedResult + * @dataProvider beforeProcessDataProvider + */ + public function testBeforeProcess($jsLayout, $activePaymentList, $expectedResult) + { + $this->store->expects($this->once())->method('getId')->willReturn(1); + $this->storeManager->expects($this->once())->method('getStore')->willReturn($this->store); + $this->paymentMethodList->expects($this->once()) + ->method('getActiveList') + ->with(1) + ->willReturn($activePaymentList); + + $result = $this->plugin->beforeProcess($this->layoutProcessor, $jsLayout); + $this->assertEquals($result[0], $expectedResult); + } + + /** + * Data provider for BeforeProcess. + * + * @return array + */ + public function beforeProcessDataProvider() + { + $jsLayout['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = [ + 'braintree' => [ + 'methods' => [ + 'braintree' => [], + 'braintree_paypal' => [] + ] + ] + ]; + $result['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = []; + + $braintreePaymentMethod = $this + ->getMockBuilder(\Magento\Payment\Api\Data\PaymentMethodInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getCode']) + ->getMockForAbstractClass(); + $braintreePaypalPaymentMethod = $this + ->getMockBuilder(\Magento\Payment\Api\Data\PaymentMethodInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getCode']) + ->getMockForAbstractClass(); + + $braintreePaymentMethod->expects($this->any())->method('getCode')->willReturn('braintree'); + $braintreePaypalPaymentMethod->expects($this->any())->method('getCode')->willReturn('braintree_paypal'); + + return [ + [$jsLayout, [], $result], + [$jsLayout, [$braintreePaymentMethod, $braintreePaypalPaymentMethod], $jsLayout] + ]; + } +} diff --git a/app/code/Magento/Payment/etc/frontend/di.xml b/app/code/Magento/Payment/etc/frontend/di.xml index 4ff3c013b6765..471a7ce9e2de5 100644 --- a/app/code/Magento/Payment/etc/frontend/di.xml +++ b/app/code/Magento/Payment/etc/frontend/di.xml @@ -19,4 +19,7 @@ + + + \ No newline at end of file diff --git a/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php b/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php new file mode 100644 index 0000000000000..fe4b88f073828 --- /dev/null +++ b/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php @@ -0,0 +1,92 @@ +vaultPaymentList = $vaultPaymentList; + $this->paymentMethodList = $paymentMethodList; + $this->storeManager = $storeManager; + } + + /** + * Checkout LayoutProcessor before process plugin. + * + * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $processor + * @param array $jsLayout + * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforeProcess(\Magento\Checkout\Block\Checkout\LayoutProcessor $processor, $jsLayout) + { + $configuration = &$jsLayout['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children']; + + if (!isset($configuration)) { + return [$jsLayout]; + } + + $storeId = $this->storeManager->getStore()->getId(); + $activePaymentMethodList = $this->paymentMethodList->getActiveList($storeId); + $activeVaultList = $this->vaultPaymentList->getActiveList($storeId); + $getCodeFunc = function($method) { + return $method->getCode(); + }; + $getProviderCodeFunc = function($method) { + return $method->getProviderCode(); + }; + $activePaymentMethodCodes = array_map($getCodeFunc, $activePaymentMethodList); + $activeVaultCodes = array_map($getCodeFunc, $activeVaultList); + $activeVaultProviderCodes = array_map($getProviderCodeFunc, $activeVaultList); + $activePaymentMethodCodes = array_merge($activePaymentMethodCodes, $activeVaultCodes, $activeVaultProviderCodes); + + foreach ($configuration as $paymentGroup => $groupConfig) { + foreach (array_keys($groupConfig['methods']) as $paymentCode) { + if (!in_array($paymentCode, $activePaymentMethodCodes)) { + unset($configuration[$paymentGroup]['methods'][$paymentCode]); + } + } + if ($paymentGroup === 'vault' && !empty($activeVaultCodes)) { + continue; + } + if (empty($configuration[$paymentGroup]['methods'])) { + unset($configuration[$paymentGroup]); + } + } + + return [$jsLayout]; + } +} diff --git a/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultConfigurationProcessTest.php b/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultConfigurationProcessTest.php new file mode 100644 index 0000000000000..0cf64c5424740 --- /dev/null +++ b/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultConfigurationProcessTest.php @@ -0,0 +1,162 @@ +storeManager = $this + ->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getStore']) + ->getMockForAbstractClass(); + $this->store = $this + ->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getId']) + ->getMockForAbstractClass(); + $this->vaultList = $this + ->getMockBuilder(\Magento\Vault\Api\PaymentMethodListInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getActiveList']) + ->getMockForAbstractClass(); + $this->paymentMethodList = $this + ->getMockBuilder(\Magento\Payment\Api\PaymentMethodListInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getActiveList']) + ->getMockForAbstractClass(); + $this->layoutProcessor = $this + ->getMockBuilder(\Magento\Checkout\Block\Checkout\LayoutProcessor::class) + ->disableOriginalConstructor() + ->setMethods(['process']) + ->getMockForAbstractClass(); + + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->plugin = $objectManagerHelper->getObject( + \Magento\Vault\Plugin\PaymentVaultConfigurationProcess::class, + [ + 'vaultPaymentList' => $this->vaultList, + 'paymentMethodList' => $this->paymentMethodList, + 'storeManager' => $this->storeManager + ] + ); + } + + /** + * @param array $jsLayout + * @param array $activeVaultList + * @param array $activePaymentList + * @param array $expectedResult + * @dataProvider beforeProcessDataProvider + */ + public function testBeforeProcess($jsLayout, $activeVaultList, $activePaymentList, $expectedResult) + { + $this->store->expects($this->once())->method('getId')->willReturn(1); + $this->storeManager->expects($this->once())->method('getStore')->willReturn($this->store); + $this->vaultList->expects($this->once())->method('getActiveList')->with(1)->willReturn($activeVaultList); + $this->paymentMethodList->expects($this->once()) + ->method('getActiveList') + ->with(1) + ->willReturn($activePaymentList); + $result = $this->plugin->beforeProcess($this->layoutProcessor, $jsLayout); + $this->assertEquals($result[0], $expectedResult); + } + + /** + * Data provider for BeforeProcess. + * + * @return array + */ + public function beforeProcessDataProvider() + { + $jsLayout['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = [ + 'vault' => [ + 'methods' => [ + 'braintree_paypal_vault' => [] + ] + ], + 'braintree' => [ + 'methods' => [ + 'braintree_paypal' => [], + 'braintree' => [] + ] + ], + 'paypal-payments' => [ + 'methods' => [ + 'payflowpro' => [], + 'payflow_link' => [] + ] + ] + ]; + $result1['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = []; + $result2['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = [ + 'vault' => [ + 'methods' => [ + 'braintree_paypal_vault' => [] + ] + ], + 'braintree' => [ + 'methods' => [ + 'braintree_paypal' => [] + ] + ] + ]; + + $vaultPaymentMethod = $this + ->getMockBuilder(\Magento\Vault\Api\PaymentMethodListInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getCode', 'getProviderCode']) + ->getMockForAbstractClass(); + + $vaultPaymentMethod->expects($this->any())->method('getCode')->willReturn('braintree_paypal_vault'); + $vaultPaymentMethod->expects($this->any())->method('getProviderCode')->willReturn('braintree_paypal'); + + return [ + [$jsLayout, [], [], $result1], + [$jsLayout, [$vaultPaymentMethod], [], $result2] + ]; + } +} diff --git a/app/code/Magento/Vault/etc/frontend/di.xml b/app/code/Magento/Vault/etc/frontend/di.xml index d7f699faff53c..0af0e4cd32217 100644 --- a/app/code/Magento/Vault/etc/frontend/di.xml +++ b/app/code/Magento/Vault/etc/frontend/di.xml @@ -19,4 +19,8 @@ Magento\Customer\Model\Session + + + + From 79f392c4f1cf43675acc09fcc80ac248a40e1635 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Thu, 3 Nov 2016 17:40:13 +0200 Subject: [PATCH 053/161] MAGETWO-60351: Unnecessary disabled payment methods on checkout page #4868 --- .../Payment/Plugin/PaymentConfigurationProcess.php | 2 +- .../Vault/Plugin/PaymentVaultConfigurationProcess.php | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php b/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php index d618ba92c23f6..b1e36b7ae39f3 100644 --- a/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php +++ b/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php @@ -53,7 +53,7 @@ public function beforeProcess(\Magento\Checkout\Block\Checkout\LayoutProcessor $ $storeId = $this->storeManager->getStore()->getId(); $activePaymentMethodList = $this->paymentMethodList->getActiveList($storeId); - $getCodeFunc = function($method) { + $getCodeFunc = function ($method) { return $method->getCode(); }; $activePaymentMethodCodes = array_map($getCodeFunc, $activePaymentMethodList); diff --git a/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php b/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php index fe4b88f073828..666e0b186309e 100644 --- a/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php +++ b/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php @@ -62,16 +62,20 @@ public function beforeProcess(\Magento\Checkout\Block\Checkout\LayoutProcessor $ $storeId = $this->storeManager->getStore()->getId(); $activePaymentMethodList = $this->paymentMethodList->getActiveList($storeId); $activeVaultList = $this->vaultPaymentList->getActiveList($storeId); - $getCodeFunc = function($method) { + $getCodeFunc = function ($method) { return $method->getCode(); }; - $getProviderCodeFunc = function($method) { + $getProviderCodeFunc = function ($method) { return $method->getProviderCode(); }; $activePaymentMethodCodes = array_map($getCodeFunc, $activePaymentMethodList); $activeVaultCodes = array_map($getCodeFunc, $activeVaultList); $activeVaultProviderCodes = array_map($getProviderCodeFunc, $activeVaultList); - $activePaymentMethodCodes = array_merge($activePaymentMethodCodes, $activeVaultCodes, $activeVaultProviderCodes); + $activePaymentMethodCodes = array_merge( + $activePaymentMethodCodes, + $activeVaultCodes, + $activeVaultProviderCodes + ); foreach ($configuration as $paymentGroup => $groupConfig) { foreach (array_keys($groupConfig['methods']) as $paymentCode) { From 0195c22e8305d93cc893fb83fd0e28c1fc250aa6 Mon Sep 17 00:00:00 2001 From: Oleksandr Dubovyk Date: Fri, 4 Nov 2016 10:21:42 +0200 Subject: [PATCH 054/161] MAGETWO-60128: [GITHUB] Customer Addresses: Can't convert undefined to object #7115 --- .../view/frontend/web/js/model/customer-addresses.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/view/frontend/web/js/model/customer-addresses.js b/app/code/Magento/Customer/view/frontend/web/js/model/customer-addresses.js index f6740550efca6..a96dca0002d69 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/model/customer-addresses.js +++ b/app/code/Magento/Customer/view/frontend/web/js/model/customer-addresses.js @@ -11,11 +11,13 @@ define( ], function($, ko, address) { "use strict"; + var isLoggedIn = ko.observable(window.isCustomerLoggedIn); + return { getAddressItems: function() { var items = []; - if (isLoggedIn) { + if (isLoggedIn()) { var customerData = window.customerData; if (Object.keys(customerData).length) { $.each(customerData.addresses, function (key, item) { @@ -23,8 +25,9 @@ define( }); } } + return items; } } } -); \ No newline at end of file +); From 0644f24c7d658a23733c51f670c1f6931be39a6f Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Fri, 4 Nov 2016 13:23:38 +0200 Subject: [PATCH 055/161] MAGETWO-60351: Unnecessary disabled payment methods on checkout page #4868 --- .../Plugin/PaymentConfigurationProcess.php | 7 +++--- .../PaymentConfigurationProcessTest.php | 23 +++++++++++++++---- .../PaymentVaultConfigurationProcess.php | 11 ++++----- .../PaymentVaultConfigurationProcessTest.php | 10 +++----- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php b/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php index b1e36b7ae39f3..5b107b74295b3 100644 --- a/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php +++ b/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php @@ -59,10 +59,9 @@ public function beforeProcess(\Magento\Checkout\Block\Checkout\LayoutProcessor $ $activePaymentMethodCodes = array_map($getCodeFunc, $activePaymentMethodList); foreach ($configuration as $paymentGroup => $groupConfig) { - foreach (array_keys($groupConfig['methods']) as $paymentCode) { - if (!in_array($paymentCode, $activePaymentMethodCodes)) { - unset($configuration[$paymentGroup]['methods'][$paymentCode]); - } + $notActivePaymentMethodCodes = array_diff(array_keys($groupConfig['methods']), $activePaymentMethodCodes); + foreach ($notActivePaymentMethodCodes as $notActivePaymentMethodCode) { + unset($configuration[$paymentGroup]['methods'][$notActivePaymentMethodCode]); } if (empty($configuration[$paymentGroup]['methods'])) { unset($configuration[$paymentGroup]); diff --git a/app/code/Magento/Payment/Test/Unit/Plugin/PaymentConfigurationProcessTest.php b/app/code/Magento/Payment/Test/Unit/Plugin/PaymentConfigurationProcessTest.php index be5755440066e..3e49c8718e604 100644 --- a/app/code/Magento/Payment/Test/Unit/Plugin/PaymentConfigurationProcessTest.php +++ b/app/code/Magento/Payment/Test/Unit/Plugin/PaymentConfigurationProcessTest.php @@ -98,6 +98,23 @@ public function testBeforeProcess($jsLayout, $activePaymentList, $expectedResult public function beforeProcessDataProvider() { $jsLayout['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = [ + 'braintree' => [ + 'methods' => [ + 'braintree_paypal' => [], + 'braintree' => [] + ] + ], + 'paypal-payments' => [ + 'methods' => [ + 'payflowpro' => [], + 'payflow_link' => [] + ] + ] + ]; + $result1['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = []; + $result2['components']['checkout']['children']['steps']['children']['billing-step'] ['children']['payment']['children']['renders']['children'] = [ 'braintree' => [ 'methods' => [ @@ -106,8 +123,6 @@ public function beforeProcessDataProvider() ] ] ]; - $result['components']['checkout']['children']['steps']['children']['billing-step'] - ['children']['payment']['children']['renders']['children'] = []; $braintreePaymentMethod = $this ->getMockBuilder(\Magento\Payment\Api\Data\PaymentMethodInterface::class) @@ -124,8 +139,8 @@ public function beforeProcessDataProvider() $braintreePaypalPaymentMethod->expects($this->any())->method('getCode')->willReturn('braintree_paypal'); return [ - [$jsLayout, [], $result], - [$jsLayout, [$braintreePaymentMethod, $braintreePaypalPaymentMethod], $jsLayout] + [$jsLayout, [], $result1], + [$jsLayout, [$braintreePaymentMethod, $braintreePaypalPaymentMethod], $result2] ]; } } diff --git a/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php b/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php index 666e0b186309e..db38ccbed417a 100644 --- a/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php +++ b/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php @@ -69,21 +69,18 @@ public function beforeProcess(\Magento\Checkout\Block\Checkout\LayoutProcessor $ return $method->getProviderCode(); }; $activePaymentMethodCodes = array_map($getCodeFunc, $activePaymentMethodList); - $activeVaultCodes = array_map($getCodeFunc, $activeVaultList); $activeVaultProviderCodes = array_map($getProviderCodeFunc, $activeVaultList); $activePaymentMethodCodes = array_merge( $activePaymentMethodCodes, - $activeVaultCodes, $activeVaultProviderCodes ); foreach ($configuration as $paymentGroup => $groupConfig) { - foreach (array_keys($groupConfig['methods']) as $paymentCode) { - if (!in_array($paymentCode, $activePaymentMethodCodes)) { - unset($configuration[$paymentGroup]['methods'][$paymentCode]); - } + $notActivePaymentMethodCodes = array_diff(array_keys($groupConfig['methods']), $activePaymentMethodCodes); + foreach ($notActivePaymentMethodCodes as $notActivePaymentMethodCode) { + unset($configuration[$paymentGroup]['methods'][$notActivePaymentMethodCode]); } - if ($paymentGroup === 'vault' && !empty($activeVaultCodes)) { + if ($paymentGroup === 'vault' && !empty($activeVaultProviderCodes)) { continue; } if (empty($configuration[$paymentGroup]['methods'])) { diff --git a/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultConfigurationProcessTest.php b/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultConfigurationProcessTest.php index 0cf64c5424740..7e7a3fd0aebdf 100644 --- a/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultConfigurationProcessTest.php +++ b/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultConfigurationProcessTest.php @@ -112,9 +112,7 @@ public function beforeProcessDataProvider() $jsLayout['components']['checkout']['children']['steps']['children']['billing-step'] ['children']['payment']['children']['renders']['children'] = [ 'vault' => [ - 'methods' => [ - 'braintree_paypal_vault' => [] - ] + 'methods' => [] ], 'braintree' => [ 'methods' => [ @@ -134,9 +132,7 @@ public function beforeProcessDataProvider() $result2['components']['checkout']['children']['steps']['children']['billing-step'] ['children']['payment']['children']['renders']['children'] = [ 'vault' => [ - 'methods' => [ - 'braintree_paypal_vault' => [] - ] + 'methods' => [] ], 'braintree' => [ 'methods' => [ @@ -156,7 +152,7 @@ public function beforeProcessDataProvider() return [ [$jsLayout, [], [], $result1], - [$jsLayout, [$vaultPaymentMethod], [], $result2] + [$jsLayout, [$vaultPaymentMethod], [$vaultPaymentMethod], $result2] ]; } } From 0ade71c5c78cdb284ae630901f6ac4f662ab4d9a Mon Sep 17 00:00:00 2001 From: Michail Slabko Date: Mon, 7 Nov 2016 12:10:31 +0200 Subject: [PATCH 056/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-60467: Simple product name not displayed as options on product page --- .../Block/Catalog/Product/View/Type/Bundle.php | 8 ++++---- app/code/Magento/Bundle/Model/Product/Type.php | 17 +---------------- .../ResourceModel/Selection/Collection.php | 17 +++-------------- .../Bundle/Pricing/Adjustment/Calculator.php | 8 ++++++-- .../Catalog/Product/View/Type/BundleTest.php | 6 +++--- .../Bundle/Test/Unit/Model/Product/TypeTest.php | 2 +- .../{Collection.php => CollectionProcessor.php} | 5 ++++- .../Model/ResourceModel/AddCatalogRulePrice.php | 6 +++--- 8 files changed, 25 insertions(+), 44 deletions(-) rename app/code/Magento/CatalogRule/Model/ResourceModel/Product/{Collection.php => CollectionProcessor.php} (97%) diff --git a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php index b413dde5c244c..9fb752be81a6c 100644 --- a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php +++ b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php @@ -49,7 +49,7 @@ class Bundle extends \Magento\Catalog\Block\Product\View\AbstractView private $selectedOptions = []; /** - * @var \Magento\CatalogRule\Model\ResourceModel\Product\Collection + * @var \Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor */ private $catalogRuleProcessor; @@ -84,13 +84,13 @@ public function __construct( /** * @deprecated - * @return \Magento\CatalogRule\Model\ResourceModel\Product\Collection + * @return \Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor */ private function getCatalogRuleProcessor() { if ($this->catalogRuleProcessor === null) { $this->catalogRuleProcessor = \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\CatalogRule\Model\ResourceModel\Product\Collection::class); + ->get(\Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor::class); } return $this->catalogRuleProcessor; @@ -114,7 +114,7 @@ public function getOptions($stripSelection = false) $optionCollection = $typeInstance->getOptionsCollection($product); - $selectionCollection = clone $typeInstance->getSelectionsCollection( + $selectionCollection = $typeInstance->getSelectionsCollection( $typeInstance->getOptionsIds($product), $product ); diff --git a/app/code/Magento/Bundle/Model/Product/Type.php b/app/code/Magento/Bundle/Model/Product/Type.php index 31789442ce63b..4cfdf27fd0e6a 100644 --- a/app/code/Magento/Bundle/Model/Product/Type.php +++ b/app/code/Magento/Bundle/Model/Product/Type.php @@ -43,6 +43,7 @@ class Type extends \Magento\Catalog\Model\Product\Type\AbstractType * Cache key for Selections Collection * * @var string + * @deprecated */ protected $_keySelectionsCollection = '_cache_instance_selections_collection'; @@ -449,22 +450,6 @@ public function getOptionsCollection($product) * @return \Magento\Bundle\Model\ResourceModel\Selection\Collection */ public function getSelectionsCollection($optionIds, $product) - { - $keyOptionIds = is_array($optionIds) ? implode('_', $optionIds) : ''; - $key = $this->_keySelectionsCollection . $keyOptionIds; - if (!$product->hasData($key)) { - $product->setData($key, $this->buildSelectionCollection($optionIds, $product)); - } - - return $product->getData($key); - } - - /** - * @param array $optionIds - * @param \Magento\Catalog\Model\Product $product - * @return \Magento\Bundle\Model\ResourceModel\Selection\Collection - */ - private function buildSelectionCollection($optionIds, $product) { $storeId = $product->getStoreId(); $selectionsCollection = $this->_bundleCollection->create() diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php index d1bbc8e7bbd40..4b64cb90c3118 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php @@ -27,7 +27,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection private $itemPrototype = null; /** - * @var \Magento\CatalogRule\Model\ResourceModel\Product\Collection + * @var \Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor */ private $catalogRuleProcessor = null; @@ -241,27 +241,16 @@ public function addPriceFilter($product, $searchMin, $useRegularPrice = false) } /** - * @return \Magento\CatalogRule\Model\ResourceModel\Product\Collection + * @return \Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor * @deprecated */ private function getCatalogRuleProcessor() { if (null === $this->catalogRuleProcessor) { $this->catalogRuleProcessor = \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\CatalogRule\Model\ResourceModel\Product\Collection::class); + ->get(\Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor::class); } return $this->catalogRuleProcessor; } - - /** - * Clear collection data after clone - * @return void - */ - public function __clone() - { - parent::__clone(); - $this->removeAttributeToSelect(); - $this->clear(); - } } diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php index b466f4600632a..7821c7f569be5 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php @@ -205,15 +205,19 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR if ($this->canSkipOption($option, $canSkipRequiredOptions)) { continue; } + /** @var \Magento\Bundle\Model\Product\Type $typeInstance */ $typeInstance = $bundleProduct->getTypeInstance(); - $selectionsCollection = clone $typeInstance->getSelectionsCollection( + $selectionsCollection = $typeInstance->getSelectionsCollection( [(int)$option->getId()], $bundleProduct ); + $selectionsCollection->removeAttributeToSelect(); $selectionsCollection->addQuantityFilter(); if ($option->isMultiSelection() && !$searchMin) { + $selectionsCollection->addPriceData(); + foreach ($selectionsCollection as $selection) { $priceList[] = $this->selectionFactory->create( $bundleProduct, @@ -284,7 +288,7 @@ protected function hasRequiredOption($bundleProduct) { /** @var \Magento\Bundle\Model\Product\Type $typeInstance */ $typeInstance = $bundleProduct->getTypeInstance(); - $collection = clone $typeInstance->getOptionsCollection($bundleProduct); + $collection = $typeInstance->getOptionsCollection($bundleProduct); return $collection->addFilter(\Magento\Bundle\Model\Option::KEY_REQUIRED, 1)->getSize() > 0; } diff --git a/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php b/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php index 72cb634127404..a0cad837e8657 100644 --- a/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php @@ -91,9 +91,9 @@ protected function setUp() ] ); - $ruleProcessor = $this->getMockBuilder(\Magento\CatalogRule\Model\ResourceModel\Product\Collection::class) - ->disableOriginalConstructor() - ->getMock(); + $ruleProcessor = $this->getMockBuilder( + \Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor::class + )->disableOriginalConstructor()->getMock(); $objectHelper->setBackwardCompatibleProperty( $this->bundleBlock, 'catalogRuleProcessor', diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php index 004e717f15680..fa18a9cb015f1 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php @@ -117,7 +117,7 @@ protected function setUp() ->getMock(); $this->catalogRuleProcessor = $this->getMockBuilder( - \Magento\CatalogRule\Model\ResourceModel\Product\Collection::class + \Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor::class ) ->disableOriginalConstructor() ->getMock(); diff --git a/app/code/Magento/CatalogRule/Model/ResourceModel/Product/Collection.php b/app/code/Magento/CatalogRule/Model/ResourceModel/Product/CollectionProcessor.php similarity index 97% rename from app/code/Magento/CatalogRule/Model/ResourceModel/Product/Collection.php rename to app/code/Magento/CatalogRule/Model/ResourceModel/Product/CollectionProcessor.php index 69dcfa59495e4..686fc3de62368 100644 --- a/app/code/Magento/CatalogRule/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/CatalogRule/Model/ResourceModel/Product/CollectionProcessor.php @@ -9,7 +9,10 @@ use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection; use Magento\CatalogRule\Pricing\Price\CatalogRulePrice; -class Collection +/** + * Add catalog rule prices to collection + */ +class CollectionProcessor { /** * @var \Magento\Store\Model\StoreManagerInterface diff --git a/app/code/Magento/CatalogRuleConfigurable/Plugin/ConfigurableProduct/Model/ResourceModel/AddCatalogRulePrice.php b/app/code/Magento/CatalogRuleConfigurable/Plugin/ConfigurableProduct/Model/ResourceModel/AddCatalogRulePrice.php index 788e43bd873a1..c7f97f770c3fb 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Plugin/ConfigurableProduct/Model/ResourceModel/AddCatalogRulePrice.php +++ b/app/code/Magento/CatalogRuleConfigurable/Plugin/ConfigurableProduct/Model/ResourceModel/AddCatalogRulePrice.php @@ -12,15 +12,15 @@ class AddCatalogRulePrice { /** - * @var \Magento\CatalogRule\Model\ResourceModel\Product\CollectionFactory + * @var \Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessorFactory */ private $catalogRuleCollectionFactory; /** - * @param \Magento\CatalogRule\Model\ResourceModel\Product\CollectionFactory $catalogRuleCollectionFactory + * @param \Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessorFactory $catalogRuleCollectionFactory */ public function __construct( - \Magento\CatalogRule\Model\ResourceModel\Product\CollectionFactory $catalogRuleCollectionFactory + \Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessorFactory $catalogRuleCollectionFactory ) { $this->catalogRuleCollectionFactory = $catalogRuleCollectionFactory; } From 7a78408fa0f4f623cd7235992ea5fbecbca733bc Mon Sep 17 00:00:00 2001 From: Iurii Ivashchenko Date: Mon, 7 Nov 2016 18:20:51 +0200 Subject: [PATCH 057/161] MAGETWO-60453: DeleteSavedCreditCardTest fails on bamboo - added alternative Visa --- .../app/Magento/Payment/Test/Repository/CreditCard.xml | 9 ++++++++- .../Vault/Test/TestCase/DeleteSavedCreditCardTest.xml | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml index b43173f568261..8e742ab30ba96 100644 --- a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml +++ b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml @@ -14,8 +14,15 @@ 123 + + 4012888888881881 + 02 - February + 2021 + 123 + + - 371449635398431 + 378282246310005 02 - February 2021 1234 diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.xml b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.xml index ac69bfb9f47e4..2cafc815fed1d 100644 --- a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.xml +++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.xml @@ -26,7 +26,7 @@ payflowpro credit_card - amex_default + visa_alt @@ -43,7 +43,7 @@ payflowpro credit_card - amex_default + visa_alt payflowpro_cc_vault From e7b9f52032639d3cd81ff8caede8ae54209689c0 Mon Sep 17 00:00:00 2001 From: Vitaliy Goncharenko Date: Tue, 1 Nov 2016 18:48:53 +0200 Subject: [PATCH 058/161] MAGETWO-53583: "Use Default" checkbox is checked again after saving empty fields (description, name, etc) - fixed integration build --- .../Eav/Model/Entity/Attribute/AbstractAttribute.php | 9 +++++++-- .../Eav/Model/ResourceModel/UpdateHandlerTest.php | 7 +------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index ba6e670ee9642..59a8e7ae2bb5e 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -22,6 +22,11 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens { const TYPE_STATIC = 'static'; + /** + * Const for empty string value. + */ + const EMPTY_STRING = ''; + /** * Attribute name * @@ -621,7 +626,7 @@ public function isValueEmpty($value) return (is_array($value) && count($value) == 0) || $value === null || ($value === false && $this->getBackend()->getType() != 'int') - || ($value === '' && $this->isInEmptyStringTypes()); + || ($value === self::EMPTY_STRING && $this->isInEmptyStringTypes()); } /** @@ -632,7 +637,7 @@ public function isValueEmpty($value) */ public function isAllowedEmptyTextValue($value) { - return $this->isInEmptyStringTypes() && $value === ''; + return $this->isInEmptyStringTypes() && $value === self::EMPTY_STRING; } /** diff --git a/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php b/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php index eb30a7d0168c6..1d5daf1e6aadf 100644 --- a/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php +++ b/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php @@ -11,12 +11,11 @@ /** * @magentoAppArea adminhtml * @magentoAppIsolation enabled + * @magentoDbIsolation enabled */ class UpdateHandlerTest extends \PHPUnit_Framework_TestCase { /** - * @magentoAppIsolation enabled - * @magentoDbIsolation enabled * @covers \Magento\Eav\Model\ResourceModel\UpdateHandler::execute * @magentoDataFixture Magento/Catalog/_files/product_simple.php * @dataProvider getAllStoresDataProvider @@ -51,8 +50,6 @@ public function testExecuteProcessForAllStores($code, $snapshotValue, $newValue, } /** - * @magentoAppIsolation enabled - * @magentoDbIsolation enabled * @covers \Magento\Eav\Model\ResourceModel\UpdateHandlerTest::execute * @magentoDataFixture Magento/Catalog/_files/product_simple.php * @magentoDataFixture Magento/Store/_files/second_store.php @@ -95,8 +92,6 @@ public function testExecuteProcessForCustomStore($code, $snapshotValue, $newValu } /** - * @magentoAppIsolation enabled - * @magentoDbIsolation enabled * @covers \Magento\Eav\Model\ResourceModel\UpdateHandlerTest::execute * @magentoDataFixture Magento/Catalog/_files/product_simple.php * @magentoDataFixture Magento/Catalog/_files/dropdown_attribute.php From 43904dbf9370cc939779b410deb0232f48332eb7 Mon Sep 17 00:00:00 2001 From: Iryna Lagno Date: Tue, 8 Nov 2016 12:42:53 +0200 Subject: [PATCH 059/161] MAGETWO-60625: [FT] AddProductsToCartBySkuFromCustomerAccountTest doesn't work --- .../Fixture/ConfigurableProduct/ConfigurableAttributesData.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php index 65f80eb714463..a816a9bab2cf7 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php @@ -275,6 +275,9 @@ protected function prepareVariationsMatrix(array $data) // generate matrix foreach ($this->attributesData as $attributeKey => $attribute) { $variationsMatrix = $this->addVariationMatrix($variationsMatrix, $attribute, $attributeKey); + if (!isset($data['matrix'])) { + $data['matrix'] = $variationsMatrix; + } } foreach ($data['matrix'] as $key => $value) { From 9d37303a35ceb1b5ed380eaf9f531e7d2f351037 Mon Sep 17 00:00:00 2001 From: Michail Slabko Date: Tue, 8 Nov 2016 13:21:24 +0200 Subject: [PATCH 060/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-60467: Simple product name not displayed as options on product page --- .../Bundle/Pricing/Adjustment/Calculator.php | 25 +++-- .../Test/Unit/Model/Product/TypeTest.php | 104 ++++++------------ .../Pricing/Adjustment/CalculatorTest.php | 69 ++++++++---- 3 files changed, 93 insertions(+), 105 deletions(-) diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php index 7821c7f569be5..6d1d172fc654e 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php @@ -209,7 +209,7 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR /** @var \Magento\Bundle\Model\Product\Type $typeInstance */ $typeInstance = $bundleProduct->getTypeInstance(); $selectionsCollection = $typeInstance->getSelectionsCollection( - [(int)$option->getId()], + [(int)$option->getOptionId()], $bundleProduct ); $selectionsCollection->removeAttributeToSelect(); @@ -239,16 +239,18 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR } $selection = $selectionsCollection->getFirstItem(); - $priceList[] = $this->selectionFactory->create( - $bundleProduct, - $selection, - $selection->getSelectionQty(), - [ - 'useRegularPrice' => $useRegularPrice, - ] - ); - } + if (!$selection->isEmpty()) { + $priceList[] = $this->selectionFactory->create( + $bundleProduct, + $selection, + $selection->getSelectionQty(), + [ + 'useRegularPrice' => $useRegularPrice, + ] + ); + } + } } if ($shouldFindMinOption) { @@ -257,10 +259,11 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR foreach ($priceList as $price) { $minPriceTmp = $price->getAmount()->getValue() * $price->getQuantity(); if (!$minPrice || $minPriceTmp < $minPrice) { + $minPrice = $minPriceTmp; $priceSelection = $price; } } - $priceList = [$priceSelection]; + $priceList = $priceSelection ? [$priceSelection] : []; } return $priceList; diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php index fa18a9cb015f1..2be68359909ef 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php @@ -208,20 +208,6 @@ public function testPrepareForCartAdvancedWithoutOptions() $product->expects($this->any()) ->method('getTypeInstance') ->willReturn($productType); - $product->expects($this->any()) - ->method('getData') - ->willReturnCallback( - function ($key) use ($optionCollection, $selectionCollection) { - $resultValue = null; - switch ($key) { - case '_cache_instance_options_collection': - $resultValue = $optionCollection; - break; - } - - return $resultValue; - } - ); $optionCollection->expects($this->any()) ->method('appendSelections') ->willReturn([$option]); @@ -2136,7 +2122,6 @@ public function testIsSalableWithRequiredOptionsTrue() 'is_salable' => true, '_cache_instance_options_collection' => $optionCollectionMock, 'status' => \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED, - '_cache_instance_selections_collection10_20_30' => $selectionCollectionMock ] ); @@ -2177,7 +2162,6 @@ public function testIsSalableWithEmptySelectionsCollection() 'is_salable' => true, '_cache_instance_options_collection' => $optionCollectionMock, 'status' => \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED, - '_cache_instance_selections_collection1' => $selectionCollectionMock ] ); @@ -2225,7 +2209,6 @@ public function nottestIsSalableWithRequiredOptionsOutOfStock() 'is_salable' => true, '_cache_instance_options_collection' => $optionCollectionMock, 'status' => \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED, - '_cache_instance_selections_collection10_20' => $selectionCollectionMock ] ); @@ -2427,38 +2410,29 @@ public function testGetSelectionsCollection() ] ) ->getMock(); - $selectionCollection = $this->getMockBuilder(\Magento\Bundle\Model\ResourceModel\Selection\Collection::class) - ->disableOriginalConstructor() - ->setMethods( - [ - 'addAttributeToSelect', - 'setFlag', - 'setPositionOrder', - 'addStoreFilter', - 'setStoreId', - 'addFilterByRequiredOptions', - 'setOptionIdsFilter', - 'joinPrices', - 'addPriceData', - 'addTierPriceData' - ] - ) - ->getMock(); $store = $this->getMockBuilder(\Magento\Store\Model\Store::class) ->disableOriginalConstructor() ->setMethods(['getWebsiteId']) ->getMock(); - $product->expects($this->once()) - ->method('hasData') - ->with('_cache_instance_selections_collection1_2_3') - ->willReturn(false); $product->expects($this->once())->method('getStoreId')->willReturn('store_id'); - $product->expects($this->at(2)) - ->method('getData') - ->with('_cache_instance_store_filter') - ->willReturn($selectionCollection); + $selectionCollection = $this->getSelectionCollection(); $this->bundleCollection->expects($this->once())->method('create')->willReturn($selectionCollection); + $this->storeManager->expects($this->once())->method('getStore')->willReturn($store); + $store->expects($this->once())->method('getWebsiteId')->willReturn('website_id'); + $selectionCollection->expects($this->any())->method('joinPrices')->with('website_id')->willReturnSelf(); + + $this->assertEquals($selectionCollection, $this->model->getSelectionsCollection($optionIds, $product)); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getSelectionCollection() + { + $selectionCollection = $this->getMockBuilder(\Magento\Bundle\Model\ResourceModel\Selection\Collection::class) + ->disableOriginalConstructor() + ->getMock(); $selectionCollection->expects($this->any())->method('addAttributeToSelect')->willReturnSelf(); $selectionCollection->expects($this->any())->method('setFlag')->willReturnSelf(); $selectionCollection->expects($this->any())->method('setPositionOrder')->willReturnSelf(); @@ -2469,19 +2443,7 @@ public function testGetSelectionsCollection() $selectionCollection->expects($this->any())->method('addPriceData')->willReturnSelf(); $selectionCollection->expects($this->any())->method('addTierPriceData')->willReturnSelf(); - $this->storeManager->expects($this->once())->method('getStore')->willReturn($store); - $store->expects($this->once())->method('getWebsiteId')->willReturn('website_id'); - $selectionCollection->expects($this->any())->method('joinPrices')->with('website_id')->willReturnSelf(); - $product->expects($this->once()) - ->method('setData') - ->with('_cache_instance_selections_collection1_2_3', $selectionCollection) - ->willReturnSelf(); - $product->expects($this->at(4)) - ->method('getData') - ->with('_cache_instance_selections_collection1_2_3') - ->willReturn($selectionCollection); - - $this->assertEquals($selectionCollection, $this->model->getSelectionsCollection($optionIds, $product)); + return $selectionCollection; } public function testProcessBuyRequest() @@ -2515,7 +2477,10 @@ public function testGetProductsToPurchaseByReqGroups() ->disableOriginalConstructor() ->setMethods(['getId', 'getRequired']) ->getMock(); - $selectionCollection = $this->getMockBuilder(\Magento\Bundle\Model\ResourceModel\Selection\Collection::class) + $selectionCollection = $this->getSelectionCollection(); + $this->bundleCollection->expects($this->once())->method('create')->willReturn($selectionCollection); + + $selectionItem = $this->getMockBuilder(\Magento\Framework\DataObject::class) ->disableOriginalConstructor() ->getMock(); @@ -2526,13 +2491,13 @@ public function testGetProductsToPurchaseByReqGroups() ->willReturn($dbResourceMock); $dbResourceMock->expects($this->once())->method('getItems')->willReturn([$item]); $item->expects($this->once())->method('getId')->willReturn('itemId'); - $product->expects($this->at(3)) - ->method('getData') - ->with('_cache_instance_selections_collectionitemId') - ->willReturn([$selectionCollection]); $item->expects($this->once())->method('getRequired')->willReturn(true); - $this->assertEquals([[$selectionCollection]], $this->model->getProductsToPurchaseByReqGroups($product)); + $selectionCollection + ->expects($this->any()) + ->method('getIterator') + ->willReturn(new \ArrayIterator([$selectionItem])); + $this->assertEquals([[$selectionItem]], $this->model->getProductsToPurchaseByReqGroups($product)); } public function testGetSearchableData() @@ -2565,14 +2530,17 @@ public function testHasOptions() ->disableOriginalConstructor() ->setMethods(['getAllIds']) ->getMock(); - $selectionCollection = $this->getMockBuilder(\Magento\Bundle\Model\ResourceModel\Selection\Collection::class) - ->disableOriginalConstructor() - ->getMock(); + $selectionCollection = $this->getSelectionCollection(); + $selectionCollection + ->expects($this->any()) + ->method('count') + ->willReturn(1); + $this->bundleCollection->expects($this->once())->method('create')->willReturn($selectionCollection); - $product->expects($this->once())->method('getStoreId')->willReturn('storeId'); + $product->expects($this->any())->method('getStoreId')->willReturn(0); $product->expects($this->once()) ->method('setData') - ->with('_cache_instance_store_filter', 'storeId') + ->with('_cache_instance_store_filter', 0) ->willReturnSelf(); $product->expects($this->any())->method('hasData')->willReturn(true); $product->expects($this->at(3)) @@ -2580,10 +2548,6 @@ public function testHasOptions() ->with('_cache_instance_options_collection') ->willReturn($optionCollection); $optionCollection->expects($this->once())->method('getAllIds')->willReturn(['ids']); - $product->expects($this->at(5)) - ->method('getData') - ->with('_cache_instance_selections_collectionids') - ->willReturn([$selectionCollection]); $this->assertTrue($this->model->hasOptions($product)); } diff --git a/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php b/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php index 2d1ac8adce5f2..87e1446b499ce 100644 --- a/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php @@ -10,7 +10,6 @@ use Magento\Bundle\Model\ResourceModel\Selection\Collection; use \Magento\Bundle\Pricing\Adjustment\Calculator; - use Magento\Bundle\Model\Product\Price as ProductPrice; use Magento\Bundle\Pricing\Price; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -139,6 +138,7 @@ public function testEmptySelectionPriceList() */ public function testGetterAmount($amountForBundle, $optionList, $expectedResult) { + $searchMin = $expectedResult['isMinAmount']; $this->baseCalculator->expects($this->atLeastOnce())->method('getAmount') ->with($this->baseAmount, $this->saleableItem) ->will($this->returnValue($this->createAmountMock($amountForBundle))); @@ -147,39 +147,55 @@ public function testGetterAmount($amountForBundle, $optionList, $expectedResult) foreach ($optionList as $optionData) { $options[] = $this->createOptionMock($optionData); } + $typeInstance = $this->getMockBuilder(\Magento\Bundle\Model\Product\Type::class) ->disableOriginalConstructor() ->getMock(); - $this->saleableItem->expects($this->any())->method('getTypeInstance')->willReturn($typeInstance); + $this->saleableItem->expects($this->atLeastOnce())->method('getTypeInstance')->willReturn($typeInstance); $optionsCollection = $this->getMockBuilder(\Magento\Bundle\Model\ResourceModel\Option\Collection::class) ->disableOriginalConstructor() ->getMock(); $optionsCollection->expects($this->atLeastOnce())->method('getIterator') ->willReturn(new \ArrayIterator($options)); - $optionsCollection->expects($this->atLeastOnce())->method('addFilter') - ->willReturnSelf(); - $optionsCollection->expects($this->atLeastOnce())->method('getSize') - ->willReturn(count($options)); + $typeInstance->expects($this->atLeastOnce())->method('getOptionsCollection')->willReturn($optionsCollection); + + + if ($searchMin) { + $optionsCollection->expects($this->atLeastOnce())->method('addFilter')->willReturnSelf(); + $optionsCollection->expects($this->atLeastOnce())->method('getSize')->willReturn(0); + $optionsCollection->expects($this->atLeastOnce())->method('getSize')->willReturn(count($options)); + } - foreach ($options as $option) { + $optionSelections = []; + foreach ($options as $index => $option) { $selectionsCollection = $this->getMockBuilder(Collection::class) ->disableOriginalConstructor() ->getMock(); - $selectionsCollection->expects($this->any())->method('getIterator') - ->willReturn(new \ArrayIterator($option->getSelections())); - $selectionsCollection->expects($this->atLeastOnce())->method('getFirstItem') - ->willReturn($option->getSelections()[0]); - $typeInstance->expects($this->atLeastOnce())->method('getSelectionsCollection') - ->willReturn($selectionsCollection); + if ($option->isMultiSelection()) { + $selectionsCollection->expects($this->any()) + ->method('getIterator') + ->willReturn(new \ArrayIterator($option->getSelections())); + $selectionsCollection->expects($this->any()) + ->method('getItems') + ->willReturn($option->getSelections()); + } else { + $selectionsCollection->expects($this->atLeastOnce()) + ->method('getFirstItem') + ->willReturn(isset($option->getSelections()[0]) ? $option->getSelections()[0] : false); + } + $optionSelections[$option->getOptionId()] = $selectionsCollection; } - $typeInstance->expects($this->atLeastOnce())->method('getOptionsCollection')->willReturn($optionsCollection); + $typeInstance->expects($this->any())->method('getSelectionsCollection') + ->willReturnCallback( + function ($optionId) use ($optionSelections) { + return $optionSelections[array_pop($optionId)]; + } + ); $price = $this->getMock(\Magento\Bundle\Pricing\Price\BundleOptionPrice::class, [], [], '', false); - $price->expects($this->atLeastOnce())->method('getOptions')->will($this->returnValue($options)); - $this->priceMocks[Price\BundleOptionPrice::PRICE_CODE] = $price; // Price type of saleable items @@ -191,7 +207,7 @@ public function testGetterAmount($amountForBundle, $optionList, $expectedResult) $this->amountFactory->expects($this->atLeastOnce())->method('create') ->with($expectedResult['fullAmount'], $expectedResult['adjustments']); - if ($expectedResult['isMinAmount']) { + if ($searchMin) { $this->model->getAmount($this->baseAmount, $this->saleableItem); } else { $this->model->getMaxAmount($this->baseAmount, $this->saleableItem); @@ -255,6 +271,11 @@ protected function createOptionMock($optionData) foreach ($optionData['selections'] as $selectionData) { $selections[] = $this->createSelectionMock($selectionData); } + if (!$selections) { + $emptyProduct = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)->disableOriginalConstructor()->getMock(); + $emptyProduct->expects($this->any())->method('isEmpty')->willReturn(true); + $selections = [$emptyProduct]; + } foreach ($optionData['data'] as $key => $value) { $option->setData($key, $value); } @@ -320,6 +341,13 @@ protected function getCaseWithMinAmount() 'required' => '1', ], 'selections' => [ + 'third product selection with the lowest price' => [ + 'data' => ['price' => 50.], + 'amount' => [ + 'adjustmentsAmounts' => ['tax' => 8, 'weee' => 10], + 'amount' => 8, + ], + ], 'first product selection' => [ 'data' => ['price' => 70.], 'amount' => [ @@ -334,13 +362,6 @@ protected function getCaseWithMinAmount() 'amount' => 28, ], ], - 'third product selection with the lowest price' => [ - 'data' => ['price' => 50.], - 'amount' => [ - 'adjustmentsAmounts' => ['tax' => 8, 'weee' => 10], - 'amount' => 8, - ], - ], ] ], ], From f4533dec11fb9cd6c62d1bb78f16ba24b434aaae Mon Sep 17 00:00:00 2001 From: Ievgen Shakhsuvarov Date: Tue, 8 Nov 2016 13:23:41 +0200 Subject: [PATCH 061/161] MAGETWO-60575: Implement Functional Test for Bundle Options on Catalog Profuct Page --- .../Block/Catalog/Product/CustomizedPrice.php | 34 ++++++ .../Test/Block/Catalog/Product/View.php | 54 +++++++++- .../AssertBundleItemsSummaryOnProductPage.php | 101 ++++++++++++++++++ .../Bundle/Test/Repository/BundleProduct.xml | 28 +++++ .../BundleProduct/BundleSelections.xml | 49 +++++++++ .../Repository/BundleProduct/CheckoutData.xml | 14 +++ .../Test/TestCase/BundleOptionsSummary.php | 34 ++++++ .../Test/TestCase/BundleOptionsSummary.xml | 17 +++ .../tests/app/Magento/Bundle/Test/etc/di.xml | 14 +++ 9 files changed, 343 insertions(+), 2 deletions(-) create mode 100644 dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/CustomizedPrice.php create mode 100644 dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleItemsSummaryOnProductPage.php create mode 100644 dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummary.php create mode 100644 dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummary.xml create mode 100644 dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/CustomizedPrice.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/CustomizedPrice.php new file mode 100644 index 0000000000000..f82bc0b83e59c --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/CustomizedPrice.php @@ -0,0 +1,34 @@ + [ + 'selector' => '.price', + ] + ]; + + /** + * This method returns the price represented by the block. + * + * @param string $currency + * @return string|null + */ + public function getFinalPrice($currency = '$') + { + return $this->getTypePrice('final_price', $currency); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View.php index db349d16a86c6..b4a9afa71fe78 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View.php +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View.php @@ -7,10 +7,8 @@ namespace Magento\Bundle\Test\Block\Catalog\Product; use Magento\Bundle\Test\Block\Catalog\Product\View\Type\Bundle; -use Magento\Bundle\Test\Fixture\BundleProduct; use Magento\Mtf\Client\Locator; use Magento\Mtf\Fixture\FixtureInterface; -use Magento\Mtf\Fixture\InjectableFixture; /** * Class View @@ -46,6 +44,20 @@ class View extends \Magento\Catalog\Test\Block\Product\View */ protected $newsletterFormSelector = '#newsletter-validate-detail[novalidate="novalidate"]'; + /** + * Selector for Bundle Summary section. + * + * @var string + */ + protected $bundleSummarySelector = '#bundle-summary > .bundle li div div'; + + /** + * Selector for Customized Bundle price block. + * + * @var string + */ + protected $customizedBundlePriceSelector = '.bundle-info'; + /** * Get bundle options block. * @@ -59,6 +71,19 @@ public function getBundleBlock() ); } + /** + * Get Bundle customized Price block. + * + * @return \Magento\Bundle\Test\Block\Catalog\Product\CustomizedPrice + */ + public function getCustomizedPriceBlock() + { + return $this->blockFactory->create( + \Magento\Bundle\Test\Block\Catalog\Product\CustomizedPrice::class, + ['element' => $this->_rootElement->find($this->customizedBundlePriceSelector)] + ); + } + /** * Click "Customize and add to cart button". * @@ -114,4 +139,29 @@ public function fillOptions(FixtureInterface $product) } $this->getBundleBlock()->fillBundleOptions($bundleCheckoutData); } + + /** + * Fill in the custom option data. + * + * @param array $optionsData + * @return void + */ + public function fillOptionsWithCustomData(array $optionsData = []) + { + if (!$this->getBundleBlock()->isVisible()) { + $this->clickCustomize(); + } + + $this->getBundleBlock()->fillBundleOptions($optionsData); + } + + /** + * Get Bundle Summary row items. + * + * @return \Magento\Mtf\Client\ElementInterface[] + */ + public function getBundleSummary() + { + return $this->_rootElement->getElements($this->bundleSummarySelector, Locator::SELECTOR_CSS); + } } diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleItemsSummaryOnProductPage.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleItemsSummaryOnProductPage.php new file mode 100644 index 0000000000000..36895dd2548a5 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleItemsSummaryOnProductPage.php @@ -0,0 +1,101 @@ +open($_ENV['app_frontend_url'] . $product->getUrlKey() . '.html'); + $bundleOptions = $product->getData()['bundle_selections']['bundle_options']; + $optionsBlock = $catalogProductView->getBundleViewBlock(); + $customizedPriceBlock = $optionsBlock->getCustomizedPriceBlock(); + foreach ($bundleOptions as $bundleOption) { + foreach ($bundleOption['assigned_products'] as $assignedProduct) { + $optionsBlock->fillOptionsWithCustomData([ + [ + 'title' => $bundleOption['title'], + 'type' => $bundleOption['type'], + 'value' => [ + 'name' => $assignedProduct['search_data']['name'] + ] + ] + ]); + $assignedProductPrice = (double)$assignedProduct['data']['selection_price_value']; + $assignedProductQty = (double)$assignedProduct['data']['selection_qty']; + + foreach ($optionsBlock->getBundleSummary() as $bundleSummaryItem) { + $bundleSummaryItemText = $bundleSummaryItem->getText(); + if (strpos($bundleSummaryItemText, $assignedProduct['search_data']['name']) !== false) { + $optionData = $this->getBundleOptionData($bundleSummaryItemText); + $optionData['price'] = (double)$customizedPriceBlock->getFinalPrice(); + $actualResult[] = $optionData; + } + } + + $expectedResult[] = [ + 'qty' => $assignedProduct['data']['selection_qty'], + 'name' => $assignedProduct['search_data']['name'], + 'price' => $assignedProductQty * $assignedProductPrice + (double)$product->getPrice() + ]; + } + } + + \PHPUnit_Framework_Assert::assertEquals( + $expectedResult, + $actualResult, + 'Bundle Summary Section does not contain correct bundle options data.' + ); + } + + /** + * Extract Bundle summary item Qty and Name from row text. + * + * @param string $rowItem + * @return array + */ + private function getBundleOptionData($rowItem) + { + // Row item must be displayed like "1 x Simple Product". + $rowItem = explode(' x ', $rowItem); + return [ + 'qty' => $rowItem[0], + 'name' => $rowItem[1] + ]; + } + + /** + * Return Text if displayed on frontend equals with fixture. + * + * @return string + */ + public function toString() + { + return 'Bundle options are displayed correctly in the summary section.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct.xml index 6a507a7a99b43..25c9e26932588 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct.xml +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct.xml @@ -184,6 +184,34 @@ bundle_required_two_fixed_options + + + Bundle fixed product %isolation% + bundle-fixed-product-%isolation% + sku_bundle_fixed_product_%isolation% + No + No + + 100 + + + taxable_goods + + 1 + No + + + default + + + Separately + + required_three_fixed_options_with_qty + + + bundle_required_three_fixed_options_with_qty + + Bundle fixed product %isolation% diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/BundleSelections.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/BundleSelections.xml index 7131aab3cffcb..584ecc0d3d0ec 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/BundleSelections.xml +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/BundleSelections.xml @@ -605,6 +605,55 @@ + + + + Drop-down Option + Drop-down + Yes + + + + %product_name% + + + 10.00 + Fixed + 1 + + + + + %product_name% + + + 20.00 + Fixed + 2 + + + + + %product_name% + + + 30.00 + Fixed + 3 + + + + + + + + catalogProductSimple::simple + catalogProductSimple::product_15_dollar + catalogProductSimple::product_40_dollar + + + + diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/CheckoutData.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/CheckoutData.xml index 3e7550b9d784e..ea88e8566a7e6 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/CheckoutData.xml +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/CheckoutData.xml @@ -357,5 +357,19 @@ + + + + + + Drop-down Option + Drop-down + + Test simple product + + + + + diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummary.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummary.php new file mode 100644 index 0000000000000..1069a09a354a5 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummary.php @@ -0,0 +1,34 @@ +persist(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummary.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummary.xml new file mode 100644 index 0000000000000..d4deff192dc05 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummary.xml @@ -0,0 +1,17 @@ + + + + + + S2 + Bundle Option with Three Drop-Down selections with qty + fixed_with_required_options_and_qty + + + + diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml new file mode 100644 index 0000000000000..402dcca44c948 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml @@ -0,0 +1,14 @@ + + + + + + S2 + + + From f5b5b786a8eb1ddfcb4a07b6244e24af94fbbf92 Mon Sep 17 00:00:00 2001 From: Ievgen Shakhsuvarov Date: Tue, 8 Nov 2016 15:59:23 +0200 Subject: [PATCH 062/161] MAGETWO-60575: Implement Functional Test for Bundle Options on Catalog Profuct Page --- .../{BundleOptionsSummary.php => BundleOptionsSummaryTest.php} | 0 .../{BundleOptionsSummary.xml => BundleOptionsSummaryTest.xml} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/{BundleOptionsSummary.php => BundleOptionsSummaryTest.php} (100%) rename dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/{BundleOptionsSummary.xml => BundleOptionsSummaryTest.xml} (100%) diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummary.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummaryTest.php similarity index 100% rename from dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummary.php rename to dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummaryTest.php diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummary.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummaryTest.xml similarity index 100% rename from dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummary.xml rename to dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummaryTest.xml From 0a0da3e01e08902e1374bc20b1add5aee98f6cf1 Mon Sep 17 00:00:00 2001 From: Ievgen Shakhsuvarov Date: Tue, 8 Nov 2016 17:37:38 +0200 Subject: [PATCH 063/161] MAGETWO-60575: Implement Functional Test for Bundle Options on Catalog Profuct Page --- .../tests/app/Magento/Bundle/Test/etc/di.xml | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml deleted file mode 100644 index 402dcca44c948..0000000000000 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - S2 - - - From 5f827773fe6379811b764adfa8ff847bf9e4d6f8 Mon Sep 17 00:00:00 2001 From: Michail Slabko Date: Tue, 8 Nov 2016 17:48:33 +0200 Subject: [PATCH 064/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-60467: Simple product name not displayed as options on product page --- .../ResourceModel/Selection/Collection.php | 4 ++-- .../Bundle/Pricing/Adjustment/Calculator.php | 16 +++++++------- .../Pricing/Price/BundleSelectionFactory.php | 10 ++------- .../Price/BundleSelectionFactoryTest.php | 22 ------------------- .../Framework/Pricing/Price/AbstractPrice.php | 2 +- 5 files changed, 13 insertions(+), 41 deletions(-) diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php index 4b64cb90c3118..d255dfc462015 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection.php @@ -177,7 +177,7 @@ public function addQuantityFilter() */ public function getNewEmptyItem() { - if ($this->itemPrototype == null) { + if (null === $this->itemPrototype) { $this->itemPrototype = parent::getNewEmptyItem(); } return clone $this->itemPrototype; @@ -200,7 +200,7 @@ public function addPriceFilter($product, $searchMin, $useRegularPrice = false) $minimalPriceExpression = 'minimal_price'; } else { $this->getCatalogRuleProcessor()->addPriceData($this, 'selection.product_id'); - $minimalPriceExpression = 'LEAST(minimal_price, IFNULL(catalog_rule_price, 99999999))'; + $minimalPriceExpression = 'LEAST(minimal_price, IFNULL(catalog_rule_price, minimal_price))'; } $orderByValue = new \Zend_Db_Expr( '(' . diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php index 6d1d172fc654e..26174e3b29ad2 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php @@ -9,7 +9,6 @@ use Magento\Bundle\Model\Product\Price; use Magento\Bundle\Pricing\Price\BundleSelectionFactory; use Magento\Catalog\Model\Product; -use Magento\Framework\App\ObjectManager; use Magento\Framework\Pricing\Adjustment\Calculator as CalculatorBase; use Magento\Framework\Pricing\Amount\AmountFactory; use Magento\Framework\Pricing\SaleableInterface; @@ -199,15 +198,16 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR } $canSkipRequiredOptions = $searchMin && !$shouldFindMinOption; + /** @var \Magento\Bundle\Model\Product\Type $typeInstance */ + $typeInstance = $bundleProduct->getTypeInstance(); $priceList = []; + foreach ($this->getBundleOptions($bundleProduct) as $option) { /** @var \Magento\Bundle\Model\Option $option */ if ($this->canSkipOption($option, $canSkipRequiredOptions)) { continue; } - /** @var \Magento\Bundle\Model\Product\Type $typeInstance */ - $typeInstance = $bundleProduct->getTypeInstance(); $selectionsCollection = $typeInstance->getSelectionsCollection( [(int)$option->getOptionId()], $bundleProduct @@ -215,7 +215,7 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR $selectionsCollection->removeAttributeToSelect(); $selectionsCollection->addQuantityFilter(); - if ($option->isMultiSelection() && !$searchMin) { + if (!$searchMin && $option->isMultiSelection()) { $selectionsCollection->addPriceData(); foreach ($selectionsCollection as $selection) { @@ -278,7 +278,7 @@ protected function getSelectionAmounts(Product $bundleProduct, $searchMin, $useR */ protected function canSkipOption($option, $canSkipRequiredOption) { - return ($canSkipRequiredOption && !$option->getRequired()); + return $canSkipRequiredOption && !$option->getRequired(); } /** @@ -289,9 +289,9 @@ protected function canSkipOption($option, $canSkipRequiredOption) */ protected function hasRequiredOption($bundleProduct) { - /** @var \Magento\Bundle\Model\Product\Type $typeInstance */ - $typeInstance = $bundleProduct->getTypeInstance(); - $collection = $typeInstance->getOptionsCollection($bundleProduct); + $collection = clone $this->getBundleOptions($bundleProduct); + $collection->clear(); + return $collection->addFilter(\Magento\Bundle\Model\Option::KEY_REQUIRED, 1)->getSize() > 0; } diff --git a/app/code/Magento/Bundle/Pricing/Price/BundleSelectionFactory.php b/app/code/Magento/Bundle/Pricing/Price/BundleSelectionFactory.php index 6a7a2329f3799..051a89943c855 100644 --- a/app/code/Magento/Bundle/Pricing/Price/BundleSelectionFactory.php +++ b/app/code/Magento/Bundle/Pricing/Price/BundleSelectionFactory.php @@ -42,7 +42,6 @@ public function __construct(\Magento\Framework\ObjectManagerInterface $objectMan * @param Product $selection * @param float $quantity * @param array $arguments - * @throws \InvalidArgumentException * @return BundleSelectionPrice */ public function create( @@ -54,12 +53,7 @@ public function create( $arguments['bundleProduct'] = $bundleProduct; $arguments['saleableItem'] = $selection; $arguments['quantity'] = $quantity ? floatval($quantity) : 1.; - $selectionPrice = $this->objectManager->create(self::SELECTION_CLASS_DEFAULT, $arguments); - if (!$selectionPrice instanceof BundleSelectionPrice) { - throw new \InvalidArgumentException( - get_class($selectionPrice) . ' doesn\'t extend BundleSelectionPrice' - ); - } - return $selectionPrice; + + return $this->objectManager->create(self::SELECTION_CLASS_DEFAULT, $arguments); } } diff --git a/app/code/Magento/Bundle/Test/Unit/Pricing/Price/BundleSelectionFactoryTest.php b/app/code/Magento/Bundle/Test/Unit/Pricing/Price/BundleSelectionFactoryTest.php index 3a0b0a22080fa..1831154043d8b 100644 --- a/app/code/Magento/Bundle/Test/Unit/Pricing/Price/BundleSelectionFactoryTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Pricing/Price/BundleSelectionFactoryTest.php @@ -66,26 +66,4 @@ public function testCreate() ->create($this->bundleMock, $this->selectionMock, 2., ['test' => 'some value']) ); } - - /** - * @expectedException \InvalidArgumentException - */ - public function testCreateException() - { - $this->objectManagerMock->expects($this->once()) - ->method('create') - ->with( - $this->equalTo(BundleSelectionFactory::SELECTION_CLASS_DEFAULT), - $this->equalTo( - [ - 'test' => 'some value', - 'bundleProduct' => $this->bundleMock, - 'saleableItem' => $this->selectionMock, - 'quantity' => 2., - ] - ) - ) - ->will($this->returnValue(new \stdClass())); - $this->bundleSelectionFactory->create($this->bundleMock, $this->selectionMock, 2., ['test' => 'some value']); - } } diff --git a/lib/internal/Magento/Framework/Pricing/Price/AbstractPrice.php b/lib/internal/Magento/Framework/Pricing/Price/AbstractPrice.php index 701cabfa358f0..6f157f578ffa5 100644 --- a/lib/internal/Magento/Framework/Pricing/Price/AbstractPrice.php +++ b/lib/internal/Magento/Framework/Pricing/Price/AbstractPrice.php @@ -23,7 +23,7 @@ abstract class AbstractPrice implements PriceInterface const PRICE_CODE = 'abstract_price'; /** - * @var AmountInterface + * @var AmountInterface[] */ protected $amount; From c3a96574dfcf9569c372b2f478d6987d9642200f Mon Sep 17 00:00:00 2001 From: Michail Slabko Date: Tue, 8 Nov 2016 18:00:12 +0200 Subject: [PATCH 065/161] MAGETWO-55729: [Customer] Optimize performance for bundled products with lots of product options - MAGETWO-60467: Simple product name not displayed as options on product page --- .../Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php b/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php index 87e1446b499ce..736190cd63b54 100644 --- a/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php @@ -168,7 +168,7 @@ public function testGetterAmount($amountForBundle, $optionList, $expectedResult) } $optionSelections = []; - foreach ($options as $index => $option) { + foreach ($options as $option) { $selectionsCollection = $this->getMockBuilder(Collection::class) ->disableOriginalConstructor() ->getMock(); From 644968634ab923ddbbf927ef9eeca338661e36a9 Mon Sep 17 00:00:00 2001 From: Vitaliy Goncharenko Date: Tue, 8 Nov 2016 19:35:24 +0200 Subject: [PATCH 066/161] MAGETWO-60283: Prices of configurable product are incorrectly recalculated when display currency is changed --- .../Magento/Catalog/Block/Product/View.php | 1 + .../Block/Product/View/Type/Configurable.php | 12 +++ ...AssertCurrencyRateAppliedOnProductPage.php | 76 +++++++++++++++++++ .../Test/TestCase/CreateCurrencyRateTest.xml | 28 +++++++ ...AssertCurrencyRateAppliedOnProductPage.php | 14 +++- .../Directory/Test/Repository/ConfigData.xml | 1 + .../Test/TestCase/CreateCurrencyRateTest.php | 30 ++++++-- .../Test/TestCase/CreateCurrencyRateTest.xml | 6 +- 8 files changed, 155 insertions(+), 13 deletions(-) create mode 100644 dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertCurrencyRateAppliedOnProductPage.php create mode 100644 dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCurrencyRateTest.xml diff --git a/app/code/Magento/Catalog/Block/Product/View.php b/app/code/Magento/Catalog/Block/Product/View.php index b100ac3643dc1..964a444a0aef8 100644 --- a/app/code/Magento/Catalog/Block/Product/View.php +++ b/app/code/Magento/Catalog/Block/Product/View.php @@ -28,6 +28,7 @@ class View extends AbstractProduct implements \Magento\Framework\DataObject\Iden /** * @var \Magento\Framework\Pricing\PriceCurrencyInterface + * @deprecated */ protected $priceCurrency; 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 1cc1cceefb399..51c68145b24cf 100644 --- a/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php @@ -92,6 +92,18 @@ public function __construct( ); } + /** + * Get cache key informative items. + * + * @return array + */ + public function getCacheKeyInfo() + { + $parentData = parent::getCacheKeyInfo(); + $parentData[] = $this->priceCurrency->getCurrencySymbol(); + return $parentData; + } + /** * Get allowed attributes * diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertCurrencyRateAppliedOnProductPage.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertCurrencyRateAppliedOnProductPage.php new file mode 100644 index 0000000000000..fdbdcc0180e4d --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertCurrencyRateAppliedOnProductPage.php @@ -0,0 +1,76 @@ +open($_ENV['app_frontend_url'] . $product->getUrlKey() . '.html'); + $this->assertPrice($view, $basePrice); + + $view->getViewBlock()->configure($product); + $this->assertPrice($view, $configuredPrices['custom_currency']); + + $cmsIndex->getCurrencyBlock()->switchCurrency($baseCurrency); + $view->getViewBlock()->configure($product); + $this->assertPrice($view, $configuredPrices['base_currency']); + } + + /** + * Assert price. + * + * @param CatalogProductView $view + * @param string $price + * @param string $currency [optional] + */ + public function assertPrice(CatalogProductView $view, $price, $currency = '') { + \PHPUnit_Framework_Assert::assertEquals( + $price, + $view->getViewBlock()->getPriceBlock()->getPrice($currency), + 'Wrong price is displayed on Product page.' + ); + } + + /** + * Returns a string representation of successful assertion. + * + * @return string + */ + public function toString() + { + return "Currency rate has been applied correctly on Configurable Product page."; + } +} diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCurrencyRateTest.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCurrencyRateTest.xml new file mode 100644 index 0000000000000..6ba7729120ae9 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCurrencyRateTest.xml @@ -0,0 +1,28 @@ + + + + + + USD + UAH + 2.000 + currency_symbols_uah + configurableProduct::default + config_base_currency_us_display_currency_uah + USD + ₴80.00 + + ₴80.00 + $40.00 + + test_type:acceptance_test + + + + + diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateAppliedOnProductPage.php b/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateAppliedOnProductPage.php index aee8b2e53c6f4..d8a2438e00c16 100644 --- a/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateAppliedOnProductPage.php +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateAppliedOnProductPage.php @@ -31,10 +31,20 @@ public function processAssert( $basePrice ) { $browser->open($_ENV['app_frontend_url'] . $product->getUrlKey() . '.html'); + $this->assertPrice($view, $basePrice); + } + /** + * Assert price. + * + * @param CatalogProductView $view + * @param string $price + * @param string $currency [optional] + */ + public function assertPrice(CatalogProductView $view, $price, $currency = '') { \PHPUnit_Framework_Assert::assertEquals( - $basePrice, - $view->getViewBlock()->getPriceBlock()->getPrice(''), + $price, + $view->getViewBlock()->getPriceBlock()->getPrice($currency), 'Wrong price is displayed on Product page.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Directory/Test/Repository/ConfigData.xml index e1ae1dc1ebfb5..7046437a0f4e2 100644 --- a/dev/tests/functional/tests/app/Magento/Directory/Test/Repository/ConfigData.xml +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/Repository/ConfigData.xml @@ -13,6 +13,7 @@ 1 UAH + USD diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.php b/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.php index 07daaff5d366f..df9cdc93a50cd 100644 --- a/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.php +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.php @@ -6,11 +6,12 @@ namespace Magento\Directory\Test\TestCase; +use Magento\Catalog\Test\TestStep\CreateProductsStep; use Magento\Config\Test\Fixture\ConfigData; use Magento\Mtf\TestCase\Injectable; use Magento\Directory\Test\Fixture\CurrencyRate; -use Magento\Catalog\Test\Fixture\CatalogProductSimple; use Magento\CurrencySymbol\Test\Page\Adminhtml\SystemCurrencyIndex; +use Magento\Mtf\TestStep\TestStepFactory; /** * Preconditions: @@ -41,29 +42,40 @@ class CreateCurrencyRateTest extends Injectable */ protected $currencyIndexPage; + /** + * Test step factory. + * + * @var TestStepFactory + */ + private $stepFactory; + /** * Inject data. * * @param SystemCurrencyIndex $currencyIndexPage - * @return void + * @param TestStepFactory $stepFactory */ - public function __inject(SystemCurrencyIndex $currencyIndexPage) + public function __inject(SystemCurrencyIndex $currencyIndexPage, TestStepFactory $stepFactory) { $this->currencyIndexPage = $currencyIndexPage; + $this->stepFactory = $stepFactory; } /** * Create currency rate test. * * @param CurrencyRate $currencyRate - * @param CatalogProductSimple $product - * @param $config - * @return void + * @param ConfigData $config + * @param string $product + * @param array $productData [optional] + * @return array */ - public function test(CurrencyRate $currencyRate, CatalogProductSimple $product, ConfigData $config) + public function test(CurrencyRate $currencyRate, ConfigData $config, $product, array $productData = []) { // Preconditions: - $product->persist(); + $product = $this->stepFactory + ->create(CreateProductsStep::class, ['products' => [$product], 'data' => $productData]) + ->run()['products'][0]; $config->persist(); // Steps: @@ -71,6 +83,8 @@ public function test(CurrencyRate $currencyRate, CatalogProductSimple $product, $this->currencyIndexPage->getCurrencyRateForm()->clickImportButton(); $this->currencyIndexPage->getCurrencyRateForm()->fill($currencyRate); $this->currencyIndexPage->getFormPageActions()->save(); + + return ['product' => $product]; } /** diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml b/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml index 083bcd5e4b0f1..e984cad9ca327 100644 --- a/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml @@ -13,7 +13,7 @@ EUR 0.8 currency_symbols_eur - simple_10_dollar + catalogProductSimple::simple_10_dollar config_currency_symbols_usd_and_eur $10.00 €8.00 @@ -25,8 +25,8 @@ UAH 2.000 currency_symbols_uah - simple_10_dollar - not_required_text_option + catalogProductSimple::simple_10_dollar + not_required_text_option config_base_currency_us_display_currency_uah ₴20.00 test_type:acceptance_test From 8f1a1bd1a0ff31db447a514c2b5a136d0a61f024 Mon Sep 17 00:00:00 2001 From: Ievgen Shakhsuvarov Date: Wed, 9 Nov 2016 09:12:21 +0200 Subject: [PATCH 067/161] MAGETWO-60575: Implement Functional Test for Bundle Options on Catalog Profuct Page --- .../Test/TestCase/BundleOptionsSummaryTest.xml | 2 +- .../tests/app/Magento/Bundle/Test/etc/di.xml | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummaryTest.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummaryTest.xml index d4deff192dc05..76ad9fd7ca116 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummaryTest.xml +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleOptionsSummaryTest.xml @@ -8,7 +8,7 @@ - S2 + severity:S2 Bundle Option with Three Drop-Down selections with qty fixed_with_required_options_and_qty diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml new file mode 100644 index 0000000000000..402dcca44c948 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml @@ -0,0 +1,14 @@ + + + + + + S2 + + + From adbf60f2f812d310f19b7e77d096793e91cd551a Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Wed, 9 Nov 2016 09:51:21 +0200 Subject: [PATCH 068/161] MAGETWO-59698: [FT] CreateWidgetEntityTestVariation4 fails to get element --- .../Catalog/Test/Block/Links/CompareLink.php | 17 +++++++++++++++++ .../AssertWidgetRecentlyComparedProducts.php | 1 + 2 files changed, 18 insertions(+) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Links/CompareLink.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Links/CompareLink.php index c81d85a724dcf..86c30f4caf8a4 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Links/CompareLink.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Links/CompareLink.php @@ -20,6 +20,13 @@ class CompareLink extends Block */ protected $qtyCompareProducts = '.compare .counter.qty'; + /** + * Locator value for Compare Products link. + * + * @var string + */ + protected $linkCompareProducts = '[data-role="compare-products-link"] a.compare'; + /** * Get qty of Products in Compare list. * @@ -32,4 +39,14 @@ public function getQtyInCompareList() preg_match_all('/^\d+/', $compareProductLink->getText(), $matches); return $matches[0][0]; } + + /** + * Wait for compare products link to appear + * + * @return void + */ + public function waitForCompareProductsLinks() + { + $this->waitForElementVisible($this->linkCompareProducts); + } } diff --git a/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetRecentlyComparedProducts.php b/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetRecentlyComparedProducts.php index 745c3afe0aa91..c32ba27b67165 100644 --- a/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetRecentlyComparedProducts.php +++ b/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetRecentlyComparedProducts.php @@ -118,6 +118,7 @@ protected function addProducts(array $products) protected function removeCompareProducts() { $this->cmsIndex->open(); + $this->cmsIndex->getCompareLinkBlock()->waitForCompareProductsLinks(); $this->cmsIndex->getLinksBlock()->openLink("Compare Products"); $this->catalogProductCompare->getCompareProductsBlock()->removeAllProducts(); } From e701cda1a80789427651fde7d187c5f9d26febe2 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Wed, 9 Nov 2016 10:57:59 +0200 Subject: [PATCH 069/161] MAGETWO-59698: [FT] CreateWidgetEntityTestVariation4 fails to get element --- .../app/Magento/Widget/Test/TestCase/CreateWidgetEntityTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Widget/Test/TestCase/CreateWidgetEntityTest.xml b/dev/tests/functional/tests/app/Magento/Widget/Test/TestCase/CreateWidgetEntityTest.xml index 225759df91f17..57920ead79a7d 100644 --- a/dev/tests/functional/tests/app/Magento/Widget/Test/TestCase/CreateWidgetEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Widget/Test/TestCase/CreateWidgetEntityTest.xml @@ -42,7 +42,7 @@ - severity:S1, stable:no + severity:S1 Recently Compared Products Magento Luma Title_%isolation% From 761059f83475daf19c7d72c9e2de152fc40100df Mon Sep 17 00:00:00 2001 From: Oleksandr Dubovyk Date: Wed, 9 Nov 2016 11:20:14 +0200 Subject: [PATCH 070/161] MAGETWO-60127: [GITHUB] Number input fields have invalid 'maxlength' attribute #7125 --- .../view/frontend/templates/product/view/addtocart.phtml | 6 +++--- .../templates/cart/item/configure/updatecart.phtml | 8 +++++++- .../view/frontend/templates/cart/item/default.phtml | 1 - .../view/frontend/web/template/minicart/item/default.html | 3 +-- .../frontend/templates/product/view/type/grouped.phtml | 4 ++-- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/addtocart.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/addtocart.phtml index eacc039255caf..ea3e8077d0dc1 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/addtocart.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/addtocart.phtml @@ -20,9 +20,9 @@ @@ -58,4 +58,4 @@ } } - \ No newline at end of file + diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/item/configure/updatecart.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/item/configure/updatecart.phtml index 0f221a393f5eb..ebe8f4570b02f 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/item/configure/updatecart.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/item/configure/updatecart.phtml @@ -17,7 +17,13 @@
- +
diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml index d83b552b05cd4..21fafe4d37f1b 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml @@ -96,7 +96,6 @@ $canApplyMsrp = $helper->isShowBeforeOrderConfirm($product) && $helper->isMinima size="4" title="escapeHtml(__('Qty')); ?>" class="input-text qty" - maxlength="12" data-validate="{required:true,'validate-greater-than-zero':true}" data-role="cart-item-qty"/> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/minicart/item/default.html b/app/code/Magento/Checkout/view/frontend/web/template/minicart/item/default.html index 89789996e5248..8796152eb6031 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/minicart/item/default.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/minicart/item/default.html @@ -79,8 +79,7 @@ }, value: qty" type="number" size="4" - class="item-qty cart-item-qty" - maxlength="12"/> + class="item-qty cart-item-qty">