diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Category/Edit/Form.php b/app/code/Magento/Catalog/Block/Adminhtml/Category/Edit/Form.php index 9cd66815ecf3e0b9307fe5732a92c968d894ad54..6ff14589e82ebfbe5435bbeef8a50cb03e45a0ae 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Category/Edit/Form.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Category/Edit/Form.php @@ -93,7 +93,7 @@ class Form extends \Magento\Catalog\Block\Adminhtml\Category\AbstractCategory 'onclick' => "categoryDelete('" . $this->getUrl( 'catalog/*/delete', ['_current' => true] - ) . "', true, {$categoryId})", + ) . "')", 'class' => 'delete' ] ); diff --git a/app/code/Magento/Catalog/Block/Navigation.php b/app/code/Magento/Catalog/Block/Navigation.php index ed8f5d99d570064c34d8a0195b8865a6e8165f1e..77c1905eed71beb27c1bf1c1e72bc231ff98f5a5 100644 --- a/app/code/Magento/Catalog/Block/Navigation.php +++ b/app/code/Magento/Catalog/Block/Navigation.php @@ -173,16 +173,6 @@ class Navigation extends \Magento\Framework\View\Element\Template implements \Ma return $this->_currentCategoryKey; } - /** - * Get catagories of current store - * - * @return \Magento\Framework\Data\Tree\Node\Collection - */ - public function getStoreCategories() - { - return $this->_catalogCategory->getStoreCategories(); - } - /** * Retrieve child categories of current category * @@ -229,161 +219,6 @@ class Navigation extends \Magento\Framework\View\Element\Template implements \Ma return $url; } - /** - * Return item position representation in menu tree - * - * @param int $level - * @return string - */ - protected function _getItemPosition($level) - { - if ($level == 0) { - $zeroLevelPosition = isset( - $this->_itemLevelPositions[$level] - ) ? $this->_itemLevelPositions[$level] + 1 : 1; - $this->_itemLevelPositions = []; - $this->_itemLevelPositions[$level] = $zeroLevelPosition; - } elseif (isset($this->_itemLevelPositions[$level])) { - $this->_itemLevelPositions[$level]++; - } else { - $this->_itemLevelPositions[$level] = 1; - } - - $position = []; - for ($i = 0; $i <= $level; $i++) { - if (isset($this->_itemLevelPositions[$i])) { - $position[] = $this->_itemLevelPositions[$i]; - } - } - return implode('-', $position); - } - - /** - * Render category to html - * - * @param Category $category - * @param int $level Nesting level number - * @param boolean $isLast Whether ot not this item is last, affects list item class - * @param boolean $isFirst Whether ot not this item is first, affects list item class - * @param boolean $isOutermost Whether ot not this item is outermost, affects list item class - * @param string $outermostItemClass Extra class of outermost list items - * @param string $childrenWrapClass If specified wraps children list in div with this class - * @param boolean $noEventAttributes Whether ot not to add on* attributes to list item - * @return string - */ - protected function _renderCategoryMenuItemHtml( - $category, - $level = 0, - $isLast = false, - $isFirst = false, - $isOutermost = false, - $outermostItemClass = '', - $childrenWrapClass = '', - $noEventAttributes = false - ) { - if (!$category->getIsActive()) { - return ''; - } - - // get all children - if ($this->flatState->isAvailable()) { - $children = (array)$category->getChildrenNodes(); - } else { - $children = $category->getChildren(); - } - - // select active children - $activeChildren = []; - foreach ($children as $child) { - if ($child->getIsActive()) { - $activeChildren[] = $child; - } - } - - $activeChildrenCount = count($activeChildren); - $hasActiveChildren = $activeChildrenCount > 0; - - // prepare list item html classes - $classes = []; - $classes[] = 'level' . $level; - $classes[] = 'nav-' . $this->_getItemPosition($level); - if ($this->isCategoryActive($category)) { - $classes[] = 'active'; - } - - $linkClass = ''; - if ($isOutermost && $outermostItemClass) { - $classes[] = $outermostItemClass; - $linkClass = ' class="' . $outermostItemClass . '"'; - } - if ($isFirst) { - $classes[] = 'first'; - } - if ($isLast) { - $classes[] = 'last'; - } - if ($hasActiveChildren) { - $classes[] = 'parent'; - } - - // prepare list item attributes - $attributes = []; - if (count($classes) > 0) { - $attributes['class'] = implode(' ', $classes); - } - if ($hasActiveChildren && !$noEventAttributes) { - $attributes['onmouseover'] = 'toggleMenu(this,1)'; - $attributes['onmouseout'] = 'toggleMenu(this,0)'; - } - - // assemble list item with attributes - $htmlLi = '<li'; - foreach ($attributes as $attrName => $attrValue) { - $htmlLi .= ' ' . $attrName . '="' . str_replace('"', '\"', $attrValue) . '"'; - } - $htmlLi .= '>'; - - $html = []; - $html[] = $htmlLi; - - $html[] = '<a href="' . $this->getCategoryUrl($category) . '"' . $linkClass . '>'; - $html[] = '<span>' . $this->escapeHtml($category->getName()) . '</span>'; - $html[] = '</a>'; - - // render children - $htmlChildren = ''; - $j = 0; - foreach ($activeChildren as $child) { - $htmlChildren .= $this->_renderCategoryMenuItemHtml( - $child, - $level + 1, - $j == $activeChildrenCount - 1, - $j == 0, - false, - $outermostItemClass, - $childrenWrapClass, - $noEventAttributes - ); - $j++; - } - if (!empty($htmlChildren)) { - if ($childrenWrapClass) { - $html[] = '<div class="' . $childrenWrapClass . '">'; - } - $html[] = '<ul class="level' . $level . '">'; - $html[] = $htmlChildren; - $html[] = '</ul>'; - if ($childrenWrapClass) { - $html[] = '</div>'; - } - } - - $html[] = '</li>'; - - $html = implode("\n", $html); - return $html; - } - /** * Enter description here... * @@ -394,107 +229,6 @@ class Navigation extends \Magento\Framework\View\Element\Template implements \Ma return $this->_catalogLayer->getCurrentCategory(); } - /** - * Enter description here... - * - * @return string - */ - public function getCurrentCategoryPath() - { - if ($this->getCurrentCategory()) { - return explode(',', $this->getCurrentCategory()->getPathInStore()); - } - return []; - } - - /** - * Enter description here... - * - * @param Category $category - * @return string - */ - public function drawOpenCategoryItem($category) - { - $html = ''; - if (!$category->getIsActive()) { - return $html; - } - - $html .= '<li'; - - if ($this->isCategoryActive($category)) { - $html .= ' class="active"'; - } - - $html .= '>' . "\n"; - $html .= '<a href="' . $this->getCategoryUrl( - $category - ) . '">' . '<span>' . $this->escapeHtml( - $category->getName() - ) . '</span></a>' . "\n"; - - if (in_array($category->getId(), $this->getCurrentCategoryPath())) { - $children = $category->getChildren(); - $hasChildren = $children && $children->count(); - - if ($hasChildren) { - $htmlChildren = ''; - foreach ($children as $child) { - $htmlChildren .= $this->drawOpenCategoryItem($child); - } - - if (!empty($htmlChildren)) { - $html .= '<ul>' . "\n" . $htmlChildren . '</ul>'; - } - } - } - $html .= '</li>' . "\n"; - - return $html; - } - - /** - * Render categories menu in HTML - * - * @param int $level Level number for list item class to start from - * @param string $outermostItemClass Extra class of outermost list items - * @param string $childrenWrapClass If specified wraps children list in div with this class - * @return string - */ - public function renderCategoriesMenuHtml($level = 0, $outermostItemClass = '', $childrenWrapClass = '') - { - $activeCategories = []; - foreach ($this->getStoreCategories() as $child) { - if ($child->getIsActive()) { - $activeCategories[] = $child; - } - } - $activeCategoriesCount = count($activeCategories); - $hasActiveCategoriesCount = $activeCategoriesCount > 0; - - if (!$hasActiveCategoriesCount) { - return ''; - } - - $html = ''; - $j = 0; - foreach ($activeCategories as $category) { - $html .= $this->_renderCategoryMenuItemHtml( - $category, - $level, - $j == $activeCategoriesCount - 1, - $j == 0, - true, - $outermostItemClass, - $childrenWrapClass, - true - ); - $j++; - } - - return $html; - } - /** * Return identifiers for produced content * diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Delete.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Delete.php index f5b053679733a438d0da357db58fc75858db8c7a..3c4eded51ce978738835e9d41cc01e32629f3a46 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Delete.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Delete.php @@ -7,6 +7,23 @@ namespace Magento\Catalog\Controller\Adminhtml\Category; class Delete extends \Magento\Catalog\Controller\Adminhtml\Category { + /** @var \Magento\Catalog\Api\CategoryRepositoryInterface */ + protected $categoryRepository; + + /** + * @param \Magento\Backend\App\Action\Context $context + * @param \Magento\Backend\Model\View\Result\RedirectFactory $resultRedirectFactory + * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository + */ + public function __construct( + \Magento\Backend\App\Action\Context $context, + \Magento\Backend\Model\View\Result\RedirectFactory $resultRedirectFactory, + \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository + ) { + parent::__construct($context, $resultRedirectFactory); + $this->categoryRepository = $categoryRepository; + } + /** * Delete category action * @@ -18,14 +35,14 @@ class Delete extends \Magento\Catalog\Controller\Adminhtml\Category $resultRedirect = $this->resultRedirectFactory->create(); $categoryId = (int)$this->getRequest()->getParam('id'); + $parentId = null; if ($categoryId) { try { - $category = $this->_objectManager->create('Magento\Catalog\Model\Category')->load($categoryId); + $category = $this->categoryRepository->get($categoryId); + $parentId = $category->getParentId(); $this->_eventManager->dispatch('catalog_controller_category_delete', ['category' => $category]); - - $this->_objectManager->get('Magento\Backend\Model\Auth\Session')->setDeletedPath($category->getPath()); - - $category->delete(); + $this->_auth->getAuthStorage()->setDeletedPath($category->getPath()); + $this->categoryRepository->delete($category); $this->messageManager->addSuccess(__('You deleted the category.')); } catch (\Magento\Framework\Model\Exception $e) { $this->messageManager->addError($e->getMessage()); @@ -35,6 +52,6 @@ class Delete extends \Magento\Catalog\Controller\Adminhtml\Category return $resultRedirect->setPath('catalog/*/edit', ['_current' => true]); } } - return $resultRedirect->setPath('catalog/*/', ['_current' => true, 'id' => null]); + return $resultRedirect->setPath('catalog/*/', ['_current' => true, 'id' => $parentId]); } } diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Edit.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Edit.php index f17bfc3abd5c1630e0e93082724eb30a8f6e1b1a..7f6dde5cb3ee101c0d2ed9f1dc3b2c1c19cf213a 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Edit.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Edit.php @@ -97,6 +97,7 @@ class Edit extends \Magento\Catalog\Controller\Adminhtml\Category . $resultPage->getLayout()->getBlock('category.tree') ->getBreadcrumbsJavascript($breadcrumbsPath, 'editingCategoryBreadcrumbs'), 'messages' => $resultPage->getLayout()->getMessagesBlock()->getGroupedHtml(), + 'toolbar' => $resultPage->getLayout()->getBlock('page.actions.toolbar')->toHtml() ]); $this->_eventManager->dispatch( 'category_prepare_ajax_response', diff --git a/app/code/Magento/Catalog/Model/Resource/Helper.php b/app/code/Magento/Catalog/Model/Resource/Helper.php index ef2f15133bd8e531a2558f802d1028dc84d004ea..fcd489d68642d628bbe7693fcf3c24cf09f5726a 100644 --- a/app/code/Magento/Catalog/Model/Resource/Helper.php +++ b/app/code/Magento/Catalog/Model/Resource/Helper.php @@ -6,14 +6,10 @@ namespace Magento\Catalog\Model\Resource; /** * Eav Mysql resource helper model - * - * @author Magento Core Team <core@magentocommerce.com> */ class Helper extends \Magento\Eav\Model\Resource\Helper { /** - * Construct - * * @param \Magento\Framework\App\Resource $resource * @param string $modulePrefix */ @@ -21,61 +17,4 @@ class Helper extends \Magento\Eav\Model\Resource\Helper { parent::__construct($resource, $modulePrefix); } - - /** - * Compare Flat style with Describe style columns - * If column a different - return false - * - * @param array $column - * @param array $describe - * @return bool - */ - public function compareIndexColumnProperties($column, $describe) - { - $type = $column['type']; - if (isset($column['length'])) { - $type = sprintf('%s(%s)', $type[0], $column['length']); - } else { - $type = $type[0]; - } - $length = null; - $precision = null; - $scale = null; - - $matches = []; - if (preg_match('/^((?:var)?char)\((\d+)\)/', $type, $matches)) { - $type = $matches[1]; - $length = $matches[2]; - } elseif (preg_match('/^decimal\((\d+),(\d+)\)/', $type, $matches)) { - $type = 'decimal'; - $precision = $matches[1]; - $scale = $matches[2]; - } elseif (preg_match('/^float\((\d+),(\d+)\)/', $type, $matches)) { - $type = 'float'; - $precision = $matches[1]; - $scale = $matches[2]; - } elseif (preg_match('/^((?:big|medium|small|tiny)?int)\((\d+)\)?/', $type, $matches)) { - $type = $matches[1]; - } - - return $describe['DATA_TYPE'] == $type && - $describe['DEFAULT'] == $column['default'] && - (bool)$describe['NULLABLE'] == (bool)$column['nullable'] && - (bool)$describe['UNSIGNED'] == (bool)$column['unsigned'] && - $describe['LENGTH'] == $length && - $describe['SCALE'] == $scale && - $describe['PRECISION'] == $precision; - } - - /** - * Getting condition isNull(f1,f2) IS NOT Null - * - * @param string $firstField - * @param string $secondField - * @return string - */ - public function getIsNullNotNullCondition($firstField, $secondField) - { - return sprintf('%s IS NOT NULL', $this->_getReadAdapter()->getIfNullSql($firstField, $secondField)); - } } diff --git a/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Eav/Source.php b/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Eav/Source.php index f88c278afe41d2d4248373f673c46989e7786291..8c8f8d5ed1302601fe726fcd91ee449be1f66ffc 100644 --- a/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Eav/Source.php +++ b/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Eav/Source.php @@ -143,6 +143,7 @@ class Source extends AbstractEav $subSelect->where('d.entity_id IN(?)', $entityIds); } + $ifNullSql = $adapter->getIfNullSql('pis.value', 'pid.value'); /**@var $select \Magento\Framework\DB\Select*/ $select = $adapter->select()->distinct(true)->from( ['pid' => new \Zend_Db_Expr(sprintf('(%s)', $subSelect->assemble()))], @@ -156,14 +157,14 @@ class Source extends AbstractEav 'pid.entity_id', 'pid.attribute_id', 'pid.store_id', - 'value' => $adapter->getIfNullSql('pis.value', 'pid.value'), + 'value' => $ifNullSql, ] )->where( 'pid.attribute_id IN(?)', $attrIds ); - $select->where($this->_resourceHelper->getIsNullNotNullCondition('pis.value', 'pid.value')); + $select->where($ifNullSql . ' IS NOT NULL'); /** * Exclude attribute values that contains NULL diff --git a/app/code/Magento/Catalog/Model/Resource/Setup.php b/app/code/Magento/Catalog/Model/Resource/Setup.php index bb2713d989c664079be242150cb4b90e357169a8..8fa1f596b380fd683324bf268fee9346b6afe4bc 100644 --- a/app/code/Magento/Catalog/Model/Resource/Setup.php +++ b/app/code/Magento/Catalog/Model/Resource/Setup.php @@ -59,23 +59,13 @@ class Setup extends \Magento\Eav\Model\Entity\Setup * * @param array $data * @return \Magento\Catalog\Model\Category + * @codeCoverageIgnore */ public function createCategory($data = []) { return $this->_categoryFactory->create($data); } - /** - * Creates eav attribute resource model - * - * @param array $data - * @return \Magento\Catalog\Model\Resource\Eav\Attribute - */ - public function createEavAttributeResource($data = []) - { - return $this->_eavAttributeResourceFactory->create($data); - } - /** * Default entites and attributes * @@ -828,41 +818,4 @@ class Setup extends \Magento\Eav\Model\Entity\Setup ] ]; } - - /** - * Returns category entity row by category id - * - * @param int $entityId - * @return array - */ - protected function _getCategoryEntityRow($entityId) - { - $select = $this->getConnection()->select(); - - $select->from($this->getTable('catalog_category_entity')); - $select->where('entity_id = :entity_id'); - - return $this->getConnection()->fetchRow($select, ['entity_id' => $entityId]); - } - - /** - * Returns category path as array - * - * @param array $category - * @param array $path - * @return string - */ - protected function _getCategoryPath($category, $path = []) - { - $path[] = $category['entity_id']; - - if ($category['parent_id'] != 0) { - $parentCategory = $this->_getCategoryEntityRow($category['parent_id']); - if ($parentCategory) { - $path = $this->_getCategoryPath($parentCategory, $path); - } - } - - return $path; - } } diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/edit.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/edit.phtml index 75b59da8d09aa3b5da4483c7fe22493056038a6d..d1d3ec2b11497fd593f8e7346144b79f4e321a0b 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/edit.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/edit.phtml @@ -34,21 +34,16 @@ require([ * This routine get categoryId explicitly, so even if currently selected tree node is out of sync * with this form, we surely delete same category in the tree and at backend */ - function categoryDelete(url, useAjax, categoryId) { + function categoryDelete(url) { if (confirm('<?php echo __('Are you sure you want to delete this category?') ?>')){ - if (useAjax){ - tree.nodeForDelete = categoryId; - updateContent(url, {}, true, true); - } else { - location.href = url; - } + location.href = url; } } /** * Update category content area */ - function updateContent(url, params, refreshTree, deleteAction) { + function updateContent(url, params, refreshTree) { var node = tree.getNodeById(tree.currentNodeId), parentNode = node && node.parentNode, parentId, @@ -64,23 +59,15 @@ require([ } (function($){ - var $categoryContainer = $('#category-edit-container'); + var $categoryContainer = $('#category-edit-container'), + messagesContainer = $('.messages'); + messagesContainer.html(''); $.ajax({ url: url + (url.match(new RegExp('\\?')) ? '&isAjax=true' : '?isAjax=true' ), data: params, context: $('body'), showLoader: true }).done(function(data){ - if (deleteAction && parentNode) { - parentId = parentNode.id; - - redirectUrl = !parentNode.isRoot ? - tree.buildUrl(parentId) : - tree.getBaseUrl(); - - location.href = redirectUrl; - } - if (data.content) { $('.page-actions').floatingHeader('destroy'); try { @@ -111,7 +98,10 @@ require([ } if (data.messages && data.messages.length > 0) { - $('.messages').html(data.messages); + messagesContainer.html(data.messages); + } + if (data.toolbar) { + $('[data-ui-id="page-actions-toolbar-content-header"]').replaceWith(data.toolbar) } }); })(jQuery); diff --git a/app/code/Magento/Catalog/view/frontend/templates/navigation/top.phtml b/app/code/Magento/Catalog/view/frontend/templates/navigation/top.phtml deleted file mode 100644 index 5eed153ff318d6d837bb7d71f307e4770356904b..0000000000000000000000000000000000000000 --- a/app/code/Magento/Catalog/view/frontend/templates/navigation/top.phtml +++ /dev/null @@ -1,28 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) - */ -?> -<?php -/** - * Top menu for store - * - * @var $this \Magento\Catalog\Block\Navigation - */ -?> -<?php -/** - * $this->renderCategoriesMenuHtml() supports optional arguments: - * int Level number for list item class to start from - * string Extra class of outermost list items - * string If specified wraps children list in div with this class - */ -?> -<?php $_menu = $this->renderCategoriesMenuHtml(0, 'level-top') ?> -<?php if ($_menu): ?> -<div class="nav container"> - <ul id="nav"> - <?php echo $_menu ?> - </ul> -</div> -<?php endif ?> diff --git a/app/code/Magento/CatalogRule/Plugin/Model/Product/Action.php b/app/code/Magento/CatalogRule/Plugin/Model/Product/Action.php new file mode 100644 index 0000000000000000000000000000000000000000..c9dbc6742abffc139f7c15d8a0cdfd32c3846aef --- /dev/null +++ b/app/code/Magento/CatalogRule/Plugin/Model/Product/Action.php @@ -0,0 +1,42 @@ +<?php +/** + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + */ + +namespace Magento\CatalogRule\Plugin\Model\Product; + +use Magento\Catalog\Model\Product\Action as ProductAction; +use Magento\CatalogRule\Model\Indexer\Product\ProductRuleProcessor; + +class Action +{ + /** + * @var ProductRuleProcessor + */ + protected $productRuleProcessor; + + /** + * @param ProductRuleProcessor $productRuleProcessor + */ + public function __construct(ProductRuleProcessor $productRuleProcessor) + { + $this->productRuleProcessor = $productRuleProcessor; + } + + /** + * @param ProductAction $object + * @param ProductAction $result + * @return ProductAction + * + * @SuppressWarnings(PHPMD.UnusedFormatParameter) + */ + public function afterUpdateAttributes(ProductAction $object, ProductAction $result) + { + $data = $result->getAttributesData(); + if (!empty($data['price'])) { + $this->productRuleProcessor->reindexList($result->getProductIds()); + } + + return $result; + } +} diff --git a/app/code/Magento/CatalogRule/etc/adminhtml/di.xml b/app/code/Magento/CatalogRule/etc/adminhtml/di.xml index 55eca2f1b83aeaedee7c4f2bdb6a2b2a5141c672..7268cb0de6eda456803dd18572bbb1cd0a1e4e75 100644 --- a/app/code/Magento/CatalogRule/etc/adminhtml/di.xml +++ b/app/code/Magento/CatalogRule/etc/adminhtml/di.xml @@ -31,4 +31,7 @@ <type name="Magento\Catalog\Model\Resource\Eav\Attribute"> <plugin name="change_product_attribute" type="Magento\CatalogRule\Plugin\Indexer\Product\Attribute"/> </type> + <type name="Magento\Catalog\Model\Product\Action"> + <plugin name="price_plugin" type="Magento\CatalogRule\Plugin\Model\Product\Action"/> + </type> </config> diff --git a/composer.json b/composer.json index 4f7d10574a1ab9a6a99c881160014a20b059cbe9..8668bc7f266953d6a866226f641c9e6e8e7e81c7 100644 --- a/composer.json +++ b/composer.json @@ -144,7 +144,6 @@ "magento/framework": "self.version", "magento/project-setup": "0.1.0", "oyejorge/less.php": "1.7.0", - "symfony/yaml": "2.3.x-dev", "trentrichardson/jquery-timepicker-addon": "1.4.3", "components/handlebars.js": "1.3.0", "colinmollenhour/cache-backend-redis": "dev-master#193d377b7fb2e88595578b282fa01a62d1185abc", diff --git a/composer.lock b/composer.lock index 1555108c6caf9966bf920872aed2e331e660096f..805bbf13580a0513996448019c7c1abe2231e84f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "92e39ae537cd58698bf74e13721f17f3", + "hash": "27bff88b2a866343d0e0bc06fc52080f", "packages": [ { "name": "composer/composer", @@ -336,17 +336,17 @@ }, { "name": "symfony/console", - "version": "v2.6.1", + "version": "v2.6.3", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "ef825fd9f809d275926547c9e57cbf14968793e8" + "reference": "6ac6491ff60c0e5a941db3ccdc75a07adbb61476" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/ef825fd9f809d275926547c9e57cbf14968793e8", - "reference": "ef825fd9f809d275926547c9e57cbf14968793e8", + "url": "https://api.github.com/repos/symfony/Console/zipball/6ac6491ff60c0e5a941db3ccdc75a07adbb61476", + "reference": "6ac6491ff60c0e5a941db3ccdc75a07adbb61476", "shasum": "" }, "require": { @@ -389,21 +389,21 @@ ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2014-12-02 20:19:20" + "time": "2015-01-06 17:50:02" }, { "name": "symfony/finder", - "version": "v2.6.1", + "version": "v2.6.3", "target-dir": "Symfony/Component/Finder", "source": { "type": "git", "url": "https://github.com/symfony/Finder.git", - "reference": "0d3ef7f6ec55a7af5eca7914eaa0dacc04ccc721" + "reference": "16513333bca64186c01609961a2bb1b95b5e1355" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/0d3ef7f6ec55a7af5eca7914eaa0dacc04ccc721", - "reference": "0d3ef7f6ec55a7af5eca7914eaa0dacc04ccc721", + "url": "https://api.github.com/repos/symfony/Finder/zipball/16513333bca64186c01609961a2bb1b95b5e1355", + "reference": "16513333bca64186c01609961a2bb1b95b5e1355", "shasum": "" }, "require": { @@ -436,21 +436,21 @@ ], "description": "Symfony Finder Component", "homepage": "http://symfony.com", - "time": "2014-12-02 20:19:20" + "time": "2015-01-03 08:01:59" }, { "name": "symfony/process", - "version": "v2.6.1", + "version": "v2.6.3", "target-dir": "Symfony/Component/Process", "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "bf0c9bd625f13b0b0bbe39919225cf145dfb935a" + "reference": "319794f611bd8bdefbac72beb3f05e847f8ebc92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/bf0c9bd625f13b0b0bbe39919225cf145dfb935a", - "reference": "bf0c9bd625f13b0b0bbe39919225cf145dfb935a", + "url": "https://api.github.com/repos/symfony/Process/zipball/319794f611bd8bdefbac72beb3f05e847f8ebc92", + "reference": "319794f611bd8bdefbac72beb3f05e847f8ebc92", "shasum": "" }, "require": { @@ -483,7 +483,7 @@ ], "description": "Symfony Process Component", "homepage": "http://symfony.com", - "time": "2014-12-02 20:19:20" + "time": "2015-01-06 22:47:52" }, { "name": "zendframework/zend-code", @@ -1876,16 +1876,16 @@ }, { "name": "league/climate", - "version": "2.5.0", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/thephpleague/climate.git", - "reference": "8687265629baaedd0fadc75350950ffc5ea53ae6" + "reference": "776b6c3b32837832a9f6d94f134b55cb7910ece6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/climate/zipball/8687265629baaedd0fadc75350950ffc5ea53ae6", - "reference": "8687265629baaedd0fadc75350950ffc5ea53ae6", + "url": "https://api.github.com/repos/thephpleague/climate/zipball/776b6c3b32837832a9f6d94f134b55cb7910ece6", + "reference": "776b6c3b32837832a9f6d94f134b55cb7910ece6", "shasum": "" }, "require": { @@ -1921,7 +1921,7 @@ "php", "terminal" ], - "time": "2014-11-08 02:33:31" + "time": "2015-01-08 02:28:23" }, { "name": "lusitanian/oauth", @@ -2833,17 +2833,17 @@ }, { "name": "symfony/config", - "version": "v2.5.8", + "version": "v2.5.9", "target-dir": "Symfony/Component/Config", "source": { "type": "git", "url": "https://github.com/symfony/Config.git", - "reference": "92f0b4c625b8c42d394b53f879d2795d84bb8c4f" + "reference": "c7309e33b719433d5cf3845d0b5b9608609d8c8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/92f0b4c625b8c42d394b53f879d2795d84bb8c4f", - "reference": "92f0b4c625b8c42d394b53f879d2795d84bb8c4f", + "url": "https://api.github.com/repos/symfony/Config/zipball/c7309e33b719433d5cf3845d0b5b9608609d8c8e", + "reference": "c7309e33b719433d5cf3845d0b5b9608609d8c8e", "shasum": "" }, "require": { @@ -2877,21 +2877,21 @@ ], "description": "Symfony Config Component", "homepage": "http://symfony.com", - "time": "2014-12-02 20:15:53" + "time": "2015-01-03 08:01:13" }, { "name": "symfony/dependency-injection", - "version": "v2.5.8", + "version": "v2.5.9", "target-dir": "Symfony/Component/DependencyInjection", "source": { "type": "git", "url": "https://github.com/symfony/DependencyInjection.git", - "reference": "b4afda3c24867a17f93237ac1fcce917cc9d7695" + "reference": "b04e6782962f8e3312274fd16fb6b37a8210a1c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/b4afda3c24867a17f93237ac1fcce917cc9d7695", - "reference": "b4afda3c24867a17f93237ac1fcce917cc9d7695", + "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/b04e6782962f8e3312274fd16fb6b37a8210a1c3", + "reference": "b04e6782962f8e3312274fd16fb6b37a8210a1c3", "shasum": "" }, "require": { @@ -2899,8 +2899,8 @@ }, "require-dev": { "symfony/config": "~2.2", - "symfony/expression-language": "~2.4", - "symfony/yaml": "~2.0" + "symfony/expression-language": "~2.4,>=2.4.10", + "symfony/yaml": "~2.1" }, "suggest": { "symfony/config": "", @@ -2934,21 +2934,21 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "http://symfony.com", - "time": "2014-12-02 21:48:32" + "time": "2015-01-05 08:51:41" }, { "name": "symfony/event-dispatcher", - "version": "v2.6.1", + "version": "v2.6.3", "target-dir": "Symfony/Component/EventDispatcher", "source": { "type": "git", "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "720fe9bca893df7ad1b4546649473b5afddf0216" + "reference": "40ff70cadea3785d83cac1c8309514b36113064e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/720fe9bca893df7ad1b4546649473b5afddf0216", - "reference": "720fe9bca893df7ad1b4546649473b5afddf0216", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/40ff70cadea3785d83cac1c8309514b36113064e", + "reference": "40ff70cadea3785d83cac1c8309514b36113064e", "shasum": "" }, "require": { @@ -2956,10 +2956,10 @@ }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.0", + "symfony/config": "~2.0,>=2.0.5", "symfony/dependency-injection": "~2.6", "symfony/expression-language": "~2.6", - "symfony/stopwatch": "~2.2" + "symfony/stopwatch": "~2.3" }, "suggest": { "symfony/dependency-injection": "", @@ -2992,21 +2992,21 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "http://symfony.com", - "time": "2014-12-02 20:19:20" + "time": "2015-01-05 14:28:40" }, { "name": "symfony/filesystem", - "version": "v2.5.8", + "version": "v2.5.9", "target-dir": "Symfony/Component/Filesystem", "source": { "type": "git", "url": "https://github.com/symfony/Filesystem.git", - "reference": "e5fc05a3a1dbb4ea0bed80fe7bd21ba3cab88c42" + "reference": "d3c24d7d6e9c342008d8421b2fade460311647ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/e5fc05a3a1dbb4ea0bed80fe7bd21ba3cab88c42", - "reference": "e5fc05a3a1dbb4ea0bed80fe7bd21ba3cab88c42", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/d3c24d7d6e9c342008d8421b2fade460311647ea", + "reference": "d3c24d7d6e9c342008d8421b2fade460311647ea", "shasum": "" }, "require": { @@ -3039,21 +3039,21 @@ ], "description": "Symfony Filesystem Component", "homepage": "http://symfony.com", - "time": "2014-12-02 20:15:53" + "time": "2015-01-03 21:04:44" }, { "name": "symfony/stopwatch", - "version": "v2.6.1", + "version": "v2.6.3", "target-dir": "Symfony/Component/Stopwatch", "source": { "type": "git", "url": "https://github.com/symfony/Stopwatch.git", - "reference": "261abd360cfb6ac65ea93ffd82073e2011d034fc" + "reference": "e8da5286132ba75ce4b4275fbf0f4cd369bfd71c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/261abd360cfb6ac65ea93ffd82073e2011d034fc", - "reference": "261abd360cfb6ac65ea93ffd82073e2011d034fc", + "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/e8da5286132ba75ce4b4275fbf0f4cd369bfd71c", + "reference": "e8da5286132ba75ce4b4275fbf0f4cd369bfd71c", "shasum": "" }, "require": { @@ -3086,7 +3086,54 @@ ], "description": "Symfony Stopwatch Component", "homepage": "http://symfony.com", - "time": "2014-12-02 20:19:20" + "time": "2015-01-03 08:01:59" + }, + { + "name": "symfony/yaml", + "version": "v2.6.3", + "target-dir": "Symfony/Component/Yaml", + "source": { + "type": "git", + "url": "https://github.com/symfony/Yaml.git", + "reference": "82462a90848a52c2533aa6b598b107d68076b018" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/82462a90848a52c2533aa6b598b107d68076b018", + "reference": "82462a90848a52c2533aa6b598b107d68076b018", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Yaml\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Yaml Component", + "homepage": "http://symfony.com", + "time": "2015-01-03 15:33:07" } ], "aliases": [], diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php index 425044b2bdd626b6dea92862fe818cc8b1a239c4..fa7d5001d208786259a3a92246fa715d6086df5e 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php @@ -328,6 +328,12 @@ return [ ['displayFullSummary', 'Magento\Tax\Model\Config'], ['displayZeroTax', 'Magento\Tax\Model\Config'], ['drawItem', 'Magento\Catalog\Block\Navigation'], + ['getStoreCategories', 'Magento\Catalog\Block\Navigation'], + ['_getItemPosition', 'Magento\Catalog\Block\Navigation'], + ['_renderCategoryMenuItemHtml', 'Magento\Catalog\Block\Navigation'], + ['getCurrentCategoryPath', 'Magento\Catalog\Block\Navigation'], + ['drawOpenCategoryItem', 'Magento\Catalog\Block\Navigation'], + ['renderCategoriesMenuHtml', 'Magento\Catalog\Block\Navigation'], ['dropKey', 'Magento\Framework\DB\Adapter\Pdo\Mysql'], ['escapeJs', 'Magento\Backend\Block\Catalog\Product\Edit\Tab\Super\Config'], ['eventClean', 'Magento\Reports\Model\Event\Observer'], @@ -2008,5 +2014,10 @@ return [ ], ['getLinksConfig', 'Magento\Downloadable\Block\Catalog\Product\Links'], ['getAuthorizationAmounts', 'Magento\Paypal\Model\Config'], - ['cleanTransactions', 'Magento\Paypal\Model\Observer'] + ['cleanTransactions', 'Magento\Paypal\Model\Observer'], + ['compareIndexColumnProperties', 'Magento\Catalog\Model\Resource\Helper'], + ['getIsNullNotNullCondition', 'Magento\Catalog\Model\Resource\Helper'], + ['_getCategoryPath', 'Magento\Catalog\Model\Resource\Setup'], + ['_getCategoryEntityRow', 'Magento\Catalog\Model\Resource\Setup'], + ['createEavAttributeResource', 'Magento\Catalog\Model\Resource\Setup'], ]; diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Controller/Adminhtml/Category/DeleteTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Controller/Adminhtml/Category/DeleteTest.php new file mode 100644 index 0000000000000000000000000000000000000000..09221eff20db82013daf71291bc185629db7b537 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Catalog/Controller/Adminhtml/Category/DeleteTest.php @@ -0,0 +1,142 @@ +<?php +/** + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + */ + +namespace Magento\Catalog\Controller\Adminhtml\Category; + +use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper; + +class DeleteTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Catalog\Controller\Adminhtml\Category\Delete */ + protected $unit; + + /** @var \Magento\Backend\Model\View\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject */ + protected $resultRedirect; + + /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $request; + + /** @var \Magento\Catalog\Api\CategoryRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $categoryRepository; + + /** @var \Magento\Backend\Model\Auth\StorageInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $authStorage; + + protected function setUp() + { + $context = $this->getMock('Magento\Backend\App\Action\Context', [], [], '', false); + $resultRedirectFactory = $this->getMock( + 'Magento\Backend\Model\View\Result\RedirectFactory', + ['create'], + [], + '', + false + ); + $this->request = $this->getMockForAbstractClass( + 'Magento\Framework\App\RequestInterface', + [], + '', + false, + true, + true, + ['getParam', 'getPost'] + ); + $auth = $this->getMock( + 'Magento\Backend\Model\Auth', + ['getAuthStorage'], + [], + '', + false + ); + $this->authStorage = $this->getMock( + 'Magento\Backend\Model\Auth\StorageInterface', + ['processLogin', 'processLogout', 'isLoggedIn', 'prolong', 'setDeletedPath'], + [], + '', + false + ); + $eventManager = $this->getMockForAbstractClass( + 'Magento\Framework\Event\ManagerInterface', + [], + '', + false, + true, + true, + ['dispatch'] + ); + $response = $this->getMockForAbstractClass( + 'Magento\Framework\App\ResponseInterface', + [], + '', + false + ); + $messageManager = $this->getMockForAbstractClass( + 'Magento\Framework\Message\ManagerInterface', + [], + '', + false, + true, + true, + ['addSuccess'] + ); + $this->categoryRepository = $this->getMock('Magento\Catalog\Api\CategoryRepositoryInterface'); + $context->expects($this->any()) + ->method('getRequest') + ->will($this->returnValue($this->request)); + $context->expects($this->any()) + ->method('getResponse') + ->will($this->returnValue($response)); + $context->expects($this->any()) + ->method('getMessageManager') + ->will($this->returnValue($messageManager)); + $context->expects($this->any()) + ->method('getEventManager') + ->will($this->returnValue($eventManager)); + $context->expects($this->any()) + ->method('getAuth') + ->will($this->returnValue($auth)); + $auth->expects($this->any()) + ->method('getAuthStorage') + ->will($this->returnValue($this->authStorage)); + + $this->resultRedirect = $this->getMock('Magento\Backend\Model\View\Result\Redirect', [], [], '', false); + $resultRedirectFactory->expects($this->any())->method('create')->willReturn($this->resultRedirect); + + $this->unit = (new ObjectManagerHelper($this))->getObject( + 'Magento\Catalog\Controller\Adminhtml\Category\Delete', + [ + 'context' => $context, + 'resultRedirectFactory' => $resultRedirectFactory, + 'categoryRepository' => $this->categoryRepository + ] + ); + } + + public function testDeleteWithoutCategoryId() + { + $this->request->expects($this->any())->method('getParam')->with('id')->willReturn(null); + $this->resultRedirect->expects($this->once())->method('setPath') + ->with('catalog/*/', ['_current' => true, 'id' => null]); + $this->categoryRepository->expects($this->never())->method('get'); + + $this->unit->execute(); + } + + public function testDelete() + { + $categoryId = 5; + $parentId = 7; + $this->request->expects($this->any())->method('getParam')->with('id')->willReturn($categoryId); + $category = $this->getMock('Magento\Catalog\Model\Category', ['getParentId', 'getPath'], [], '', false); + $category->expects($this->once())->method('getParentId')->willReturn($parentId); + $category->expects($this->once())->method('getPath')->willReturn('category-path'); + $this->categoryRepository->expects($this->once())->method('get')->with($categoryId)->willReturn($category); + $this->authStorage->expects($this->once())->method('setDeletedPath')->with('category-path'); + $this->resultRedirect->expects($this->once())->method('setPath') + ->with('catalog/*/', ['_current' => true, 'id' => $parentId]); + + $this->unit->execute(); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/SetupTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/SetupTest.php new file mode 100644 index 0000000000000000000000000000000000000000..557582b27a5035e74157f753fb8e472e895c14c7 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/SetupTest.php @@ -0,0 +1,107 @@ +<?php +/** + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + */ +namespace Magento\Catalog\Model\Resource; + +class SetupTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Catalog\Model\Resource\Setup */ + protected $unit; + + protected function setUp() + { + $this->unit = (new \Magento\TestFramework\Helper\ObjectManager($this))->getObject( + 'Magento\Catalog\Model\Resource\Setup' + ); + } + + public function testGetDefaultEntitiesContainAllAttributes() + { + $defaultEntities = $this->unit->getDefaultEntities(); + + $this->assertEquals( + [ + 'name', + 'is_active', + 'description', + 'image', + 'meta_title', + 'meta_keywords', + 'meta_description', + 'display_mode', + 'landing_page', + 'is_anchor', + 'path', + 'position', + 'all_children', + 'path_in_store', + 'children', + 'custom_design', + 'custom_design_from', + 'custom_design_to', + 'page_layout', + 'custom_layout_update', + 'level', + 'children_count', + 'available_sort_by', + 'default_sort_by', + 'include_in_menu', + 'custom_use_parent_settings', + 'custom_apply_to_products', + 'filter_price_range', + ], + array_keys($defaultEntities['catalog_category']['attributes']) + ); + + $this->assertEquals( + [ + 'name', + 'sku', + 'description', + 'short_description', + 'price', + 'special_price', + 'special_from_date', + 'special_to_date', + 'cost', + 'weight', + 'manufacturer', + 'meta_title', + 'meta_keyword', + 'meta_description', + 'image', + 'small_image', + 'thumbnail', + 'media_gallery', + 'old_id', + 'group_price', + 'tier_price', + 'color', + 'news_from_date', + 'news_to_date', + 'gallery', + 'status', + 'minimal_price', + 'visibility', + 'custom_design', + 'custom_design_from', + 'custom_design_to', + 'custom_layout_update', + 'page_layout', + 'category_ids', + 'options_container', + 'required_options', + 'has_options', + 'image_label', + 'small_image_label', + 'thumbnail_label', + 'created_at', + 'updated_at', + 'country_of_manufacture', + 'quantity_and_stock_status', + ], + array_keys($defaultEntities['catalog_product']['attributes']) + ); + } +} diff --git a/dev/tests/unit/testsuite/Magento/CatalogRule/Plugin/Model/Product/ActionTest.php b/dev/tests/unit/testsuite/Magento/CatalogRule/Plugin/Model/Product/ActionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..189e4b63018d71651287e8817f60accba65bc133 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/CatalogRule/Plugin/Model/Product/ActionTest.php @@ -0,0 +1,79 @@ +<?php +/** + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + */ + +namespace Magento\CatalogRule\Plugin\Model\Product; + +class ActionTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\CatalogRule\Plugin\Model\Product\Action */ + protected $action; + + /** @var \Magento\CatalogRule\Model\Indexer\Product\ProductRuleProcessor|\PHPUnit_Framework_MockObject_MockObject */ + protected $productRuleProcessor; + + protected function setUp() + { + $this->productRuleProcessor = $this->getMockBuilder( + 'Magento\CatalogRule\Model\Indexer\Product\ProductRuleProcessor' + )->disableOriginalConstructor() + ->setMethods(['reindexList']) + ->getMock(); + + $this->action = new Action($this->productRuleProcessor); + } + + public function testAfterUpdateAttributes() + { + $subject = $this->getMockBuilder('Magento\Catalog\Model\Product\Action') + ->disableOriginalConstructor() + ->setMethods([]) + ->getMock(); + + $result = $this->getMockBuilder('Magento\Catalog\Model\Product\Action') + ->disableOriginalConstructor() + ->setMethods(['getAttributesData', 'getProductIds']) + ->getMock(); + + $result->expects($this->once()) + ->method('getAttributesData') + ->willReturn([]); + + $result->expects($this->never()) + ->method('getProductIds'); + + $this->productRuleProcessor->expects($this->never()) + ->method('reindexList'); + + $this->action->afterUpdateAttributes($subject, $result); + } + + public function testAfterUpdateAttributesWithPrice() + { + $productIds = [1, 2, 3]; + $subject = $this->getMockBuilder('Magento\Catalog\Model\Product\Action') + ->disableOriginalConstructor() + ->setMethods([]) + ->getMock(); + + $result = $this->getMockBuilder('Magento\Catalog\Model\Product\Action') + ->disableOriginalConstructor() + ->setMethods(['getAttributesData', 'getProductIds']) + ->getMock(); + + $result->expects($this->once()) + ->method('getAttributesData') + ->willReturn(['price' => 100]); + + $result->expects($this->once()) + ->method('getProductIds') + ->willReturn($productIds); + + $this->productRuleProcessor->expects($this->once()) + ->method('reindexList') + ->with($productIds); + + $this->action->afterUpdateAttributes($subject, $result); + } +}