diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Helper/Form/Wysiwyg/Content.php b/app/code/Magento/Catalog/Block/Adminhtml/Helper/Form/Wysiwyg/Content.php index d5488ecc5d085ee4a5d4b535ccf24040dbaee2a6..ac8cb91222fba47c7c686c10b45d6b81e87db2eb 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Helper/Form/Wysiwyg/Content.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Helper/Form/Wysiwyg/Content.php @@ -14,6 +14,12 @@ namespace Magento\Catalog\Block\Adminhtml\Helper\Form\Wysiwyg; use Magento\Backend\Block\Widget\Form; use Magento\Backend\Block\Widget\Form\Generic; +/** + * Class Content + * + * @deprecated + * @see \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav + */ class Content extends Generic { /** diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassStatus.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassStatus.php index 6dae249865157d1c5960c8be6cefa9bdf27b3126..43114cb83ad149ff07a2310ec1924dcd6f9faa25 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassStatus.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassStatus.php @@ -84,6 +84,11 @@ class MassStatus extends \Magento\Catalog\Controller\Adminhtml\Product $productIds = $collection->getAllIds(); $storeId = (int) $this->getRequest()->getParam('store', 0); $status = (int) $this->getRequest()->getParam('status'); + $filters = (array)$this->getRequest()->getParam('filters', []); + + if (isset($filters['store_id'])) { + $storeId = (int)$filters['store_id']; + } try { $this->_validateMassStatus($productIds, $status); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Save.php index c984840e2067daa0f43f06319e9c3a68b1287012..6e432447263ee9d4d6240a6c104b6c599db1e81c 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Save.php @@ -101,6 +101,9 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product\Set } $model->save(); $this->messageManager->addSuccess(__('You saved the attribute set.')); + } catch (\Magento\Framework\Exception\AlreadyExistsException $e) { + $this->messageManager->addErrorMessage($e->getMessage()); + $hasError = true; } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); $hasError = true; diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php index 327729cf83695931a8c378dc91f41ab66a9e7d69..290770bd296c3bf9ef8854de86008674776ae2b7 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php @@ -73,9 +73,12 @@ class Sku extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend { $attribute = $this->getAttribute(); $entity = $attribute->getEntity(); - $increment = $this->_getLastSimilarAttributeValueIncrement($attribute, $object); $attributeValue = $object->getData($attribute->getAttributeCode()); + $increment = null; while (!$entity->checkAttributeUniqueValue($attribute, $object)) { + if ($increment === null) { + $increment = $this->_getLastSimilarAttributeValueIncrement($attribute, $object); + } $sku = trim($attributeValue); if (strlen($sku . '-' . ++$increment) > self::SKU_MAX_LENGTH) { $sku = substr($sku, 0, -strlen($increment) - 1); diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php index f17760237034041764539e533d5f1440b8dad3e4..cbf0464ca366158d4d3e4d75f65e4435f0834502 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php @@ -58,6 +58,11 @@ class CreateHandler implements ExtensionInterface */ protected $fileStorageDb; + /** + * @var array + */ + private $mediaAttributeCodes; + /** * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool * @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository @@ -145,9 +150,11 @@ class CreateHandler implements ExtensionInterface } /* @var $mediaAttribute \Magento\Catalog\Api\Data\ProductAttributeInterface */ - foreach ($this->mediaConfig->getMediaAttributeCodes() as $mediaAttrCode) { + foreach ($this->getMediaAttributeCodes() as $mediaAttrCode) { $attrData = $product->getData($mediaAttrCode); - + if (empty($attrData) && empty($clearImages) && empty($newImages) && empty($existImages)) { + continue; + } if (in_array($attrData, $clearImages)) { $product->setData($mediaAttrCode, 'no_selection'); } @@ -394,4 +401,17 @@ class CreateHandler implements ExtensionInterface ); } } + + /** + * Get Media Attribute Codes cached value + * + * @return array + */ + private function getMediaAttributeCodes() + { + if ($this->mediaAttributeCodes === null) { + $this->mediaAttributeCodes = $this->mediaConfig->getMediaAttributeCodes(); + } + return $this->mediaAttributeCodes; + } } diff --git a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php index 3df4d9813a668b6fc81d7706412e1cf4e671c5e5..167dc2be15b292c4fabd9983911cd54cba89e62c 100644 --- a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php @@ -40,7 +40,6 @@ class SaveHandler Link $linkResource, ProductLinkRepositoryInterface $productLinkRepository ) { - $this->metadataPool = $metadataPool; $this->linkResource = $linkResource; $this->productLinkRepository = $productLinkRepository; @@ -54,12 +53,18 @@ class SaveHandler */ public function execute($entityType, $entity) { - /** @var \Magento\Catalog\Api\Data\ProductInterface $entity*/ - foreach ($this->productLinkRepository->getList($entity) as $link) { - $this->productLinkRepository->delete($link); + $link = $entity->getData($this->metadataPool->getMetadata($entityType)->getLinkField()); + if ($this->linkResource->hasProductLinks($link)) { + /** @var \Magento\Catalog\Api\Data\ProductInterface $entity*/ + foreach ($this->productLinkRepository->getList($entity) as $link) { + $this->productLinkRepository->delete($link); + } } - foreach ($entity->getProductLinks() as $link) { - $this->productLinkRepository->save($link); + $productLinks = $entity->getProductLinks(); + if (count($productLinks) > 0) { + foreach ($entity->getProductLinks() as $link) { + $this->productLinkRepository->save($link); + } } return $entity; } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category.php b/app/code/Magento/Catalog/Model/ResourceModel/Category.php index 407c2027923de4c683272773d519cf1adc7b1917..e743c5d384bdd539a15c4f666b36ce0f43f7f4d0 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Category.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Category.php @@ -238,7 +238,9 @@ class Category extends AbstractResource if (!$object->getChildrenCount()) { $object->setChildrenCount(0); } - + $object->setAttributeSetId( + $object->getAttributeSetId() ?: $this->getEntityType()->getDefaultAttributeSetId() + ); if ($object->isObjectNew()) { if ($object->getPosition() === null) { $object->setPosition($this->_getMaxPosition($object->getPath()) + 1); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php index 99c4316d20740edc4d3d6415bbfb06a344e7e5c7..8e93868dc7e51916a1c44997ad98045edbe1bd4f 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php @@ -351,14 +351,11 @@ class Attribute extends \Magento\Eav\Model\Entity\Attribute implements */ public function getApplyTo() { - if ($this->getData(self::APPLY_TO)) { - if (is_array($this->getData(self::APPLY_TO))) { - return $this->getData(self::APPLY_TO); - } - return explode(',', $this->getData(self::APPLY_TO)); - } else { - return []; + $applyTo = $this->_getData(self::APPLY_TO) ?: []; + if (!is_array($applyTo)) { + $applyTo = explode(',', $applyTo); } + return $applyTo; } /** diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Link.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Link.php index bbccabe5a61c969f74294398ad484e1b0d3c64f9..17bfa90e8842d4dc511d8d78f2dc23151a3934b3 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Link.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Link.php @@ -96,6 +96,30 @@ class Link extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb return $connection->fetchOne($select, $bind); } + /** + * Check if product has links. + * + * @param int $parentId ID of product + * @return bool + */ + public function hasProductLinks($parentId) + { + $connection = $this->getConnection(); + $select = $connection->select()->from( + $this->getMainTable(), + ['count' => new \Zend_Db_Expr('COUNT(*)')] + )->where( + 'product_id = :product_id' + ) ; + + return $connection->fetchOne( + $select, + [ + 'product_id' => $parentId + ] + ) > 0; + } + /** * Save Product Links process * diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/MassStatusTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/MassStatusTest.php index 0fff613c56e2e4edc5a6765826730ffefac89f10..6f7809d89e5bda52429f5c365f1fdd8519996189 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/MassStatusTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/MassStatusTest.php @@ -6,32 +6,74 @@ */ namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Product; +use Magento\Ui\Component\MassAction\Filter; +use Magento\Backend\Model\View\Result\Redirect; +use Magento\Catalog\Model\Indexer\Product\Price\Processor; +use Magento\Catalog\Controller\Adminhtml\Product\Builder; +use Magento\Framework\Data\Collection\AbstractDb; +use Magento\Catalog\Model\Product\Action; + +/** + * Class MassStatusTest + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class MassStatusTest extends \Magento\Catalog\Test\Unit\Controller\Adminhtml\ProductTest { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var Processor|\PHPUnit_Framework_MockObject_MockObject */ - protected $priceProcessor; + private $priceProcessorMock; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Backend\Model\View\Result\Redirect */ - protected $resultRedirect; + /** + * @var Redirect|\PHPUnit_Framework_MockObject_MockObject + */ + private $resultRedirectMock; + + /** + * @var Filter|\PHPUnit_Framework_MockObject_MockObject + */ + private $filterMock; + + /** + * @var Builder|\PHPUnit_Framework_MockObject_MockObject + */ + private $productBuilderMock; + + /** + * @var AbstractDb|\PHPUnit_Framework_MockObject_MockObject + */ + private $abstractDbMock; + + /** + * @var Action|\PHPUnit_Framework_MockObject_MockObject + */ + private $actionMock; protected function setUp() { - $this->priceProcessor = $this->getMockBuilder(\Magento\Catalog\Model\Indexer\Product\Price\Processor::class) + $this->priceProcessorMock = $this->getMockBuilder(Processor::class) ->disableOriginalConstructor()->getMock(); + $this->productBuilderMock = $this->getMockBuilder(Builder::class) + ->setMethods(['build']) + ->disableOriginalConstructor() + ->getMock(); - $productBuilder = $this->getMockBuilder( - \Magento\Catalog\Controller\Adminhtml\Product\Builder::class - )->setMethods(['build'])->disableOriginalConstructor()->getMock(); - - $product = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)->disableOriginalConstructor() - ->setMethods(['getTypeId', 'getStoreId', '__sleep', '__wakeup'])->getMock(); - $product->expects($this->any())->method('getTypeId')->will($this->returnValue('simple')); - $product->expects($this->any())->method('getStoreId')->will($this->returnValue('1')); - $productBuilder->expects($this->any())->method('build')->will($this->returnValue($product)); + $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) + ->disableOriginalConstructor() + ->setMethods(['getTypeId', 'getStoreId', '__sleep', '__wakeup']) + ->getMock(); + $productMock->expects($this->any()) + ->method('getTypeId') + ->willReturn('simple'); + $productMock->expects($this->any()) + ->method('getStoreId') + ->willReturn('1'); + $this->productBuilderMock->expects($this->any()) + ->method('build') + ->willReturn($productMock); - $this->resultRedirect = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Redirect::class) + $this->resultRedirectMock = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Redirect::class) ->disableOriginalConstructor() ->getMock(); $resultFactory = $this->getMockBuilder(\Magento\Framework\Controller\ResultFactory::class) @@ -41,47 +83,71 @@ class MassStatusTest extends \Magento\Catalog\Test\Unit\Controller\Adminhtml\Pro $resultFactory->expects($this->atLeastOnce()) ->method('create') ->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT) - ->willReturn($this->resultRedirect); + ->willReturn($this->resultRedirectMock); - $abstractDbMock = $this->getMockBuilder(\Magento\Framework\Data\Collection\AbstractDb::class) + $this->abstractDbMock = $this->getMockBuilder(AbstractDb::class) ->disableOriginalConstructor() ->setMethods(['getAllIds', 'getResource']) ->getMock(); - $abstractDbMock->expects($this->any()) - ->method('getAllIds') - ->willReturn([]); - - $filterMock = $this->getMockBuilder(\Magento\Ui\Component\MassAction\Filter::class) + $this->filterMock = $this->getMockBuilder(\Magento\Ui\Component\MassAction\Filter::class) ->disableOriginalConstructor() ->setMethods(['getCollection']) ->getMock(); - $filterMock->expects($this->any()) - ->method('getCollection') - ->willReturn($abstractDbMock); - - $collectionFactoryMock = $this->getMockBuilder( - \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory::class - ) + $this->actionMock = $this->getMockBuilder(Action::class) + ->disableOriginalConstructor() + ->getMock(); + + $collectionFactoryMock = + $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory::class) ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); $collectionFactoryMock->expects($this->any()) ->method('create') - ->willReturn($abstractDbMock); + ->willReturn($this->abstractDbMock); + + $additionalParams = [ + 'resultFactory' => $resultFactory + ]; + /** @var \Magento\Backend\App\Action\Context $context */ + $context = $this->initContext($additionalParams, [[Action::class, $this->actionMock]]); - $additionalParams = ['resultFactory' => $resultFactory]; $this->action = new \Magento\Catalog\Controller\Adminhtml\Product\MassStatus( - $this->initContext($additionalParams), - $productBuilder, - $this->priceProcessor, - $filterMock, + $context, + $this->productBuilderMock, + $this->priceProcessorMock, + $this->filterMock, $collectionFactoryMock ); } public function testMassStatusAction() { - $this->priceProcessor->expects($this->once())->method('reindexList'); + $storeId = 1; + $status = \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED; + $filters = [ + 'store_id' => 2, + ]; + + $this->filterMock->expects($this->once()) + ->method('getCollection') + ->willReturn($this->abstractDbMock); + $this->abstractDbMock->expects($this->once()) + ->method('getAllIds') + ->willReturn([3]); + $this->request->expects($this->exactly(3)) + ->method('getParam') + ->willReturnMap([ + ['store', 0, $storeId], + ['status', null, $status], + ['filters', [], $filters] + ]); + $this->actionMock->expects($this->once()) + ->method('updateAttributes') + ->with([3], ['status' => $status], 2); + $this->priceProcessorMock->expects($this->once()) + ->method('reindexList'); + $this->action->execute(); } } diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/ProductTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/ProductTest.php index 9a21de70b4f114fceb5950ea716c580068584669..524bdceae10e03cfc9678f10d19b881588ff8de8 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/ProductTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/ProductTest.php @@ -5,6 +5,8 @@ */ namespace Magento\Catalog\Test\Unit\Controller\Adminhtml; +use Magento\Catalog\Api\Data\ProductInterface; + /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -25,17 +27,33 @@ abstract class ProductTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject */ protected $request; + /** + * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $objectManagerMock; + /** * Init context object * * @param array $additionalParams + * @param array $objectManagerMap Object Manager mappings * @return \PHPUnit_Framework_MockObject_MockObject */ - protected function initContext(array $additionalParams = []) + protected function initContext(array $additionalParams = [], array $objectManagerMap = []) { $productActionMock = $this->getMock(\Magento\Catalog\Model\Product\Action::class, [], [], '', false); - $objectManagerMock = $this->getMockForAbstractClass(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('get')->will($this->returnValue($productActionMock)); + + $this->objectManagerMock = $this->getMockForAbstractClass(\Magento\Framework\ObjectManagerInterface::class); + + if ($objectManagerMap) { + $this->objectManagerMock->expects($this->any()) + ->method('get') + ->willReturnMap($objectManagerMap); + } + + $this->objectManagerMock->expects($this->any()) + ->method('get') + ->willReturn($productActionMock); $block = $this->getMockBuilder(\Magento\Framework\View\Element\AbstractBlock::class) ->disableOriginalConstructor()->getMockForAbstractClass(); @@ -93,7 +111,7 @@ abstract class ProductTest extends \PHPUnit_Framework_TestCase $this->context->expects($this->any())->method('getEventManager')->will($this->returnValue($eventManager)); $this->context->expects($this->any())->method('getRequest')->will($this->returnValue($requestInterfaceMock)); $this->context->expects($this->any())->method('getResponse')->will($this->returnValue($responseInterfaceMock)); - $this->context->expects($this->any())->method('getObjectManager')->will($this->returnValue($objectManagerMock)); + $this->context->expects($this->any())->method('getObjectManager')->willReturn($this->objectManagerMock); $this->context->expects($this->any())->method('getMessageManager') ->will($this->returnValue($managerInterfaceMock)); diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index 1419c17e11b298d1fcdc554a3131d7b8c9b8ffe8..e1680ab5a4081946b73b375a85c0b53cf916afd4 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -754,7 +754,10 @@ class Eav extends AbstractModifier $meta['arguments']['data']['config']['wysiwyg'] = true; $meta['arguments']['data']['config']['wysiwygConfigData'] = [ 'add_variables' => false, - 'add_widgets' => false + 'add_widgets' => false, + 'add_directives' => true, + 'use_container' => true, + 'container_class' => 'hor-scroll', ]; return $meta; diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php index 86b150062d3c057afe500a6d76aac3665690ba87..fa704272962162d43edd1d129c1229275614015a 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php @@ -5,7 +5,6 @@ */ namespace Magento\CatalogImportExport\Model\Export; -use Magento\Framework\DB\Ddl\Table; use Magento\ImportExport\Model\Import; use \Magento\Store\Model\Store; use \Magento\CatalogImportExport\Model\Import\Product as ImportProduct; @@ -850,6 +849,24 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity return $writer->getContents(); } + /** + * {@inheritdoc} + */ + protected function _prepareEntityCollection(\Magento\Eav\Model\Entity\Collection\AbstractCollection $collection) + { + $exportFilter = !empty($this->_parameters[\Magento\ImportExport\Model\Export::FILTER_ELEMENT_GROUP]) ? + $this->_parameters[\Magento\ImportExport\Model\Export::FILTER_ELEMENT_GROUP] : []; + + if (isset($exportFilter['category_ids']) + && trim($exportFilter['category_ids']) + && $collection instanceof \Magento\Catalog\Model\ResourceModel\Product\Collection + ) { + $collection->addCategoriesFilter(['in' => explode(',', $exportFilter['category_ids'])]); + } + + return parent::_prepareEntityCollection($collection); + } + /** * Get export data for collection * @@ -953,7 +970,7 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity if (is_scalar($attrValue)) { if (!in_array($fieldName, $this->_getExportMainAttrCodes())) { $additionalAttributes[$fieldName] = $fieldName . - ImportProduct::PAIR_NAME_VALUE_SEPARATOR . $attrValue; + ImportProduct::PAIR_NAME_VALUE_SEPARATOR . $this->wrapValue($attrValue); } $data[$itemId][$storeId][$fieldName] = htmlspecialchars_decode($attrValue); } @@ -963,7 +980,7 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity $additionalAttributes[$code] = $fieldName . ImportProduct::PAIR_NAME_VALUE_SEPARATOR . implode( ImportProduct::PSEUDO_MULTI_LINE_SEPARATOR, - $this->collectedMultiselectsData[$storeId][$productLinkId][$code] + $this->wrapValue($this->collectedMultiselectsData[$storeId][$productLinkId][$code]) ); } } @@ -994,6 +1011,25 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity return $data; } + /** + * Wrap values with double quotes if "Fields Enclosure" option is enabled + * + * @param string|array $value + * @return string|array + */ + private function wrapValue($value) + { + if (!empty($this->_parameters[\Magento\ImportExport\Model\Export::FIELDS_ENCLOSURE])) { + $wrap = function ($value) { + return sprintf('"%s"', str_replace('"', '""', $value)); + }; + + $value = is_array($value) ? array_map($wrap, $value) : $wrap($value); + } + + return $value; + } + /** * @return array */ diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index 16df0866135a7f07760134c7aff9a0b15bc6fb01..afb2e86b6248a79523405c78acd1cf27953b90c2 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -644,6 +644,13 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity */ private $productEntityIdentifierField; + /** + * Escaped separator value for regular expression. + * The value is based on PSEUDO_MULTI_LINE_SEPARATOR constant. + * @var string + */ + private $multiLineSeparatorForRegexp; + /** * @param \Magento\Framework\Json\Helper\Data $jsonHelper * @param \Magento\ImportExport\Helper\Data $importExportData @@ -2438,14 +2445,40 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity } /** - * Retrieves additional attributes as array code=>value. + * Retrieves additional attributes in format: + * [ + * code1 => value1, + * code2 => value2, + * ... + * codeN => valueN + * ] * - * @param string $additionalAttributes + * @param string $additionalAttributes Attributes data that will be parsed * @return array */ private function parseAdditionalAttributes($additionalAttributes) { - $attributeNameValuePairs = explode($this->getMultipleValueSeparator(), $additionalAttributes); + return empty($this->_parameters[Import::FIELDS_ENCLOSURE]) + ? $this->parseAttributesWithoutWrappedValues($additionalAttributes) + : $this->parseAttributesWithWrappedValues($additionalAttributes); + } + + /** + * Parses data and returns attributes in format: + * [ + * code1 => value1, + * code2 => value2, + * ... + * codeN => valueN + * ] + * + * @param string $attributesData Attributes data that will be parsed. It keeps data in format: + * code=value,code2=value2...,codeN=valueN + * @return array + */ + private function parseAttributesWithoutWrappedValues($attributesData) + { + $attributeNameValuePairs = explode($this->getMultipleValueSeparator(), $attributesData); $preparedAttributes = []; $code = ''; foreach ($attributeNameValuePairs as $attributeData) { @@ -2463,6 +2496,75 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity return $preparedAttributes; } + /** + * Parses data and returns attributes in format: + * [ + * code1 => value1, + * code2 => value2, + * ... + * codeN => valueN + * ] + * All values have unescaped data except mupliselect attributes, + * they should be parsed in additional method - parseMultiselectValues() + * + * @param string $attributesData Attributes data that will be parsed. It keeps data in format: + * code="value",code2="value2"...,codeN="valueN" + * where every value is wrapped in double quotes. Double quotes as part of value should be duplicated. + * E.g. attribute with code 'attr_code' has value 'my"value'. This data should be stored as attr_code="my""value" + * + * @return array + */ + private function parseAttributesWithWrappedValues($attributesData) + { + $attributes = []; + preg_match_all('~((?:[a-z0-9_])+)="((?:[^"]|""|"' . $this->getMultiLineSeparatorForRegexp() . '")+)"+~', + $attributesData, + $matches + ); + foreach ($matches[1] as $i => $attributeCode) { + $attribute = $this->retrieveAttributeByCode($attributeCode); + $value = 'multiselect' != $attribute->getFrontendInput() + ? str_replace('""', '"', $matches[2][$i]) + : '"' . $matches[2][$i] . '"'; + $attributes[$attributeCode] = $value; + } + return $attributes; + } + + /** + * Parse values of multiselect attributes depends on "Fields Enclosure" parameter + * + * @param string $values + * @return array + */ + public function parseMultiselectValues($values) + { + if (empty($this->_parameters[Import::FIELDS_ENCLOSURE])) { + return explode(self::PSEUDO_MULTI_LINE_SEPARATOR, $values); + } + if (preg_match_all('~"((?:[^"]|"")*)"~', $values, $matches)) { + return $values = array_map(function ($value) { + return str_replace('""', '"', $value); + }, $matches[1]); + } + return [$values]; + } + + /** + * Retrieves escaped PSEUDO_MULTI_LINE_SEPARATOR if it is metacharacter for regular expression + * + * @return string + */ + private function getMultiLineSeparatorForRegexp() + { + if (!$this->multiLineSeparatorForRegexp) { + $this->multiLineSeparatorForRegexp = in_array(self::PSEUDO_MULTI_LINE_SEPARATOR, str_split('[\^$.|?*+(){}')) + ? '\\' . self::PSEUDO_MULTI_LINE_SEPARATOR + : self::PSEUDO_MULTI_LINE_SEPARATOR; + } + return $this->multiLineSeparatorForRegexp; + } + /** * Set values in use_config_ fields. * diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php index 8461e617431d64fe3529162d54841d7da4740cdf..0d19b9fcbedc85e4df47ab745759282f4824b060 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php @@ -490,23 +490,25 @@ abstract class AbstractType $resultAttrs = []; foreach ($this->_getProductAttributes($rowData) as $attrCode => $attrParams) { - if (!$attrParams['is_static']) { - if (isset($rowData[$attrCode]) && strlen($rowData[$attrCode])) { - $resultAttrs[$attrCode] = in_array($attrParams['type'], ['select', 'boolean']) - ? $attrParams['options'][strtolower($rowData[$attrCode])] - : $rowData[$attrCode]; - if ('multiselect' == $attrParams['type']) { - $resultAttrs[$attrCode] = []; - foreach (explode(Product::PSEUDO_MULTI_LINE_SEPARATOR, $rowData[$attrCode]) as $value) { - $resultAttrs[$attrCode][] = $attrParams['options'][strtolower($value)]; - } - $resultAttrs[$attrCode] = implode(',', $resultAttrs[$attrCode]); + if ($attrParams['is_static']) { + continue; + } + if (isset($rowData[$attrCode]) && strlen($rowData[$attrCode])) { + if (in_array($attrParams['type'], ['select', 'boolean'])) { + $resultAttrs[$attrCode] = $attrParams['options'][strtolower($rowData[$attrCode])]; + } elseif ('multiselect' == $attrParams['type']) { + $resultAttrs[$attrCode] = []; + foreach ($this->_entityModel->parseMultiselectValues($rowData[$attrCode]) as $value) { + $resultAttrs[$attrCode][] = $attrParams['options'][strtolower($value)]; } - } elseif (array_key_exists($attrCode, $rowData)) { + $resultAttrs[$attrCode] = implode(',', $resultAttrs[$attrCode]); + } else { $resultAttrs[$attrCode] = $rowData[$attrCode]; - } elseif ($withDefaultValue && null !== $attrParams['default_value']) { - $resultAttrs[$attrCode] = $attrParams['default_value']; } + } elseif (array_key_exists($attrCode, $rowData)) { + $resultAttrs[$attrCode] = $rowData[$attrCode]; + } elseif ($withDefaultValue && null !== $attrParams['default_value']) { + $resultAttrs[$attrCode] = $attrParams['default_value']; } } diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php index e57983796f695fcac97325123d102cbe5a9854b7..0ca40e916c85b0fe50886f36fe502538a370ae50 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php @@ -71,6 +71,32 @@ class Validator extends AbstractValidator implements RowValidatorInterface return $valid; } + /** + * Check if value is valid attribute option + * + * @param string $attrCode + * @param array $possibleOptions + * @param string $value + * @return bool + */ + private function validateOption($attrCode, $possibleOptions, $value) + { + if (!isset($possibleOptions[strtolower($value)])) { + $this->_addMessages( + [ + sprintf( + $this->context->retrieveMessageTemplate( + RowValidatorInterface::ERROR_INVALID_ATTRIBUTE_OPTION + ), + $attrCode + ) + ] + ); + return false; + } + return true; + } + /** * @param mixed $attrCode * @param string $type @@ -166,23 +192,15 @@ class Validator extends AbstractValidator implements RowValidatorInterface break; case 'select': case 'boolean': + $valid = $this->validateOption($attrCode, $attrParams['options'], $rowData[$attrCode]); + break; case 'multiselect': - $values = explode(Product::PSEUDO_MULTI_LINE_SEPARATOR, $rowData[$attrCode]); - $valid = true; + $values = $this->context->parseMultiselectValues($rowData[$attrCode]); foreach ($values as $value) { - $valid = $valid && isset($attrParams['options'][strtolower($value)]); - } - if (!$valid) { - $this->_addMessages( - [ - sprintf( - $this->context->retrieveMessageTemplate( - RowValidatorInterface::ERROR_INVALID_ATTRIBUTE_OPTION - ), - $attrCode - ) - ] - ); + $valid = $this->validateOption($attrCode, $attrParams['options'], $value); + if (!$valid) { + break; + } } break; case 'datetime': diff --git a/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php b/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php index c5cdd1950cc3803a238bdd77caa1ee5fa2f8b88e..58e364920bb6ad4919212ba329e2d8294cd36027 100644 --- a/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php +++ b/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php @@ -15,13 +15,14 @@ use Magento\CatalogInventory\Model\Indexer\Stock\Processor; use Magento\CatalogInventory\Model\ResourceModel\Stock\Item as StockItemResource; use Magento\CatalogInventory\Model\Spi\StockStateProviderInterface; use Magento\CatalogInventory\Model\StockRegistryStorage; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\MapperFactory; use Magento\Framework\DB\QueryBuilderFactory; use Magento\Framework\Exception\CouldNotDeleteException; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Framework\Stdlib\DateTime\TimezoneInterface; use Magento\Framework\Stdlib\DateTime\DateTime; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; /** * Class StockItemRepository @@ -89,6 +90,9 @@ class StockItemRepository implements StockItemRepositoryInterface */ protected $stockRegistryStorage; + /** @var \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory */ + protected $productCollectionFactory; + /** * @param StockConfigurationInterface $stockConfiguration * @param StockStateProviderInterface $stockStateProvider @@ -129,6 +133,21 @@ class StockItemRepository implements StockItemRepositoryInterface $this->dateTime = $dateTime; } + /** + * @deprecated + * @return \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory + */ + private function getProductCollectionFactory() + { + if ($this->productCollectionFactory === null) { + $this->productCollectionFactory = ObjectManager::getInstance()->get( + \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory::class + ); + } + + return $this->productCollectionFactory; + } + /** * @inheritdoc */ @@ -136,8 +155,12 @@ class StockItemRepository implements StockItemRepositoryInterface { try { /** @var \Magento\Catalog\Model\Product $product */ - $product = $this->productFactory->create(); - $product->load($stockItem->getProductId()); + $product = $this->getProductCollectionFactory()->create() + ->setFlag('has_stock_status_filter') + ->addIdFilter($stockItem->getProductId()) + ->addFieldToSelect('type_id') + ->getFirstItem(); + if (!$product->getId()) { return $stockItem; } diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php index 769e2db4cc84553a3a10e081e6785a02a72b5d15..23b7805e622e32938a3403e58af7f30d8a8d80e8 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php @@ -5,6 +5,8 @@ */ namespace Magento\CatalogInventory\Test\Unit\Model\Stock; +use Magento\Catalog\Model\ResourceModel\Product\Collection; +use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory; use Magento\CatalogInventory\Model\Stock\StockItemRepository; use Magento\CatalogInventory\Api\Data as InventoryApiData; use Magento\CatalogInventory\Model\StockRegistryStorage; @@ -153,9 +155,8 @@ class StockItemRepositoryTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->setMethods(['load', 'getId', 'getTypeId', '__wakeup']) ->getMock(); - $this->productFactoryMock->expects($this->any()) - ->method('create') - ->willReturn($this->productMock); + + $this->productFactoryMock->expects($this->any())->method('create')->willReturn($this->productMock); $this->queryBuilderFactoryMock = $this->getMockBuilder(\Magento\Framework\DB\QueryBuilderFactory::class) ->setMethods(['create']) @@ -185,6 +186,22 @@ class StockItemRepositoryTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); + $productCollection = $this->getMockBuilder( + \Magento\Catalog\Model\ResourceModel\Product\Collection::class + )->disableOriginalConstructor()->getMock(); + + $productCollection->expects($this->any())->method('setFlag')->willReturnSelf(); + $productCollection->expects($this->any())->method('addIdFilter')->willReturnSelf(); + $productCollection->expects($this->any())->method('addFieldToSelect')->willReturnSelf(); + $productCollection->expects($this->any())->method('getFirstItem')->willReturn($this->productMock); + + $productCollectionFactory = $this->getMockBuilder(CollectionFactory::class) + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $productCollectionFactory->expects($this->any())->method('create')->willReturn($productCollection); + $this->model = (new ObjectManager($this))->getObject( StockItemRepository::class, [ @@ -200,6 +217,7 @@ class StockItemRepositoryTest extends \PHPUnit_Framework_TestCase 'indexProcessor' => $this->indexProcessorMock, 'dateTime' => $this->dateTime, 'stockRegistryStorage' => $this->stockRegistryStorage, + 'productCollectionFactory' => $productCollectionFactory, ] ); } @@ -263,7 +281,6 @@ class StockItemRepositoryTest extends \PHPUnit_Framework_TestCase $productId = 1; $this->stockItemMock->expects($this->any())->method('getProductId')->willReturn($productId); - $this->productMock->expects($this->once())->method('load')->with($productId)->willReturnSelf(); $this->productMock->expects($this->once())->method('getId')->willReturn($productId); $this->productMock->expects($this->once())->method('getTypeId')->willReturn('typeId'); $this->stockConfigurationMock->expects($this->once())->method('isQty')->with('typeId')->willReturn(true); @@ -309,7 +326,6 @@ class StockItemRepositoryTest extends \PHPUnit_Framework_TestCase $productId = 1; $this->stockItemMock->expects($this->any())->method('getProductId')->willReturn($productId); - $this->productMock->expects($this->once())->method('load')->with($productId)->willReturnSelf(); $this->productMock->expects($this->once())->method('getId')->willReturn(null); $this->stockRegistryStorage->expects($this->never())->method('removeStockItem'); $this->stockRegistryStorage->expects($this->never())->method('removeStockStatus'); @@ -325,7 +341,6 @@ class StockItemRepositoryTest extends \PHPUnit_Framework_TestCase $productId = 1; $this->stockItemMock->expects($this->any())->method('getProductId')->willReturn($productId); - $this->productMock->expects($this->once())->method('load')->with($productId)->willReturnSelf(); $this->productMock->expects($this->once())->method('getId')->willReturn($productId); $this->productMock->expects($this->once())->method('getTypeId')->willReturn('typeId'); $this->stockConfigurationMock->expects($this->once())->method('isQty')->with('typeId')->willReturn(false); diff --git a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurations.php b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurations.php index ea24235b0fe2ef694e2087f7a8bdbf4c8ece3399..cb9a6b534609f7205f2c8a569b022389e13436b7 100644 --- a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurations.php +++ b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurations.php @@ -32,7 +32,7 @@ class UpdateConfigurations 'swatch_image', 'small_image', 'thumbnail', - 'image' + 'image', ]; /** @@ -65,13 +65,15 @@ class UpdateConfigurations ) { $configurations = $this->getConfigurations(); $configurations = $this->variationHandler->duplicateImagesForVariations($configurations); - foreach ($configurations as $productId => $productData) { - /** @var \Magento\Catalog\Model\Product $product */ - $product = $this->productRepository->getById($productId, false, $this->request->getParam('store', 0)); - $productData = $this->variationHandler->processMediaGallery($product, $productData); - $product->addData($productData); - if ($product->hasDataChanges()) { - $product->save(); + if (count($configurations)) { + foreach ($configurations as $productId => $productData) { + /** @var \Magento\Catalog\Model\Product $product */ + $product = $this->productRepository->getById($productId, false, $this->request->getParam('store', 0)); + $productData = $this->variationHandler->processMediaGallery($product, $productData); + $product->addData($productData); + if ($product->hasDataChanges()) { + $product->save(); + } } } return $configurableProduct; @@ -91,6 +93,12 @@ class UpdateConfigurations } foreach ($configurableMatrix as $item) { + if (empty($item['was_changed'])) { + continue; + } else { + unset($item['was_changed']); + } + if (!$item['newProduct']) { $result[$item['id']] = $this->mapData($item); diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php b/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php index 321870b96d32abf13c48fdc0975efc9ba5248f17..0d0bba60a7777c75deef4bc9e0a41720b9597163 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php @@ -29,6 +29,9 @@ class VariationHandler /** @var \Magento\Catalog\Model\ProductFactory */ protected $productFactory; + /** @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute[] */ + private $attributes; + /** * @var \Magento\CatalogInventory\Api\StockConfigurationInterface * @deprecated @@ -70,6 +73,7 @@ class VariationHandler public function generateSimpleProducts($parentProduct, $productsData) { $generatedProductIds = []; + $this->attributes = null; $productsData = $this->duplicateImagesForVariations($productsData); foreach ($productsData as $simpleProductData) { $newSimpleProduct = $this->productFactory->create(); @@ -160,7 +164,10 @@ class VariationHandler $parentProduct->getNewVariationsAttributeSetId() ); - foreach ($product->getTypeInstance()->getSetAttributes($product) as $attribute) { + if ($this->attributes === null) { + $this->attributes = $product->getTypeInstance()->getSetAttributes($product); + } + foreach ($this->attributes as $attribute) { if ($attribute->getIsUnique() || $attribute->getAttributeCode() == 'url_key' || $attribute->getFrontend()->getInputType() == 'gallery' || diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurationsTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurationsTest.php index bed5c96b5216eb76344e9ce593ea56056be9a35b..def49f42fa960b738fe952be4a2d18bada61ffd2 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurationsTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurationsTest.php @@ -90,13 +90,24 @@ class UpdateConfigurationsTest extends \PHPUnit_Framework_TestCase 'swatch_image' => 'simple2_swatch_image', 'small_image' => 'simple2_small_image', 'thumbnail' => 'simple2_thumbnail', - 'image' => 'simple2_image' + 'image' => 'simple2_image', + 'was_changed' => true, ], [ 'newProduct' => false, 'id' => 'product3', - 'qty' => '3' - ] + 'qty' => '3', + 'was_changed' => true, + ], + [ + 'newProduct' => false, + 'id' => 'product4', + 'status' => 'simple4_status', + 'sku' => 'simple2_sku', + 'name' => 'simple2_name', + 'price' => '3.33', + 'weight' => '5.55', + ], ]; $configurations = [ 'product2' => [ @@ -118,8 +129,8 @@ class UpdateConfigurationsTest extends \PHPUnit_Framework_TestCase ]; /** @var Product[]|\PHPUnit_Framework_MockObject_MockObject[] $productMocks */ $productMocks = [ - 'product2' => $this->getProductMock($configurations['product2'], true), - 'product3' => $this->getProductMock($configurations['product3']) + 'product2' => $this->getProductMock($configurations['product2'], true, true), + 'product3' => $this->getProductMock($configurations['product3'], false, true), ]; $this->requestMock->expects(static::any()) @@ -161,26 +172,27 @@ class UpdateConfigurationsTest extends \PHPUnit_Framework_TestCase * @param bool $hasDataChanges * @return Product|\PHPUnit_Framework_MockObject_MockObject */ - protected function getProductMock(array $expectedData = null, $hasDataChanges = false) + protected function getProductMock(array $expectedData = null, $hasDataChanges = false, $wasChanged = false) { $productMock = $this->getMockBuilder(Product::class) ->disableOriginalConstructor() ->getMock(); - if ($expectedData !== null) { - $productMock->expects(static::once()) - ->method('addData') - ->with($expectedData) + if ($wasChanged !== false) { + if ($expectedData !== null) { + $productMock->expects(static::once()) + ->method('addData') + ->with($expectedData) + ->willReturnSelf(); + } + + $productMock->expects(static::any()) + ->method('hasDataChanges') + ->willReturn($hasDataChanges); + $productMock->expects($hasDataChanges ? static::once() : static::never()) + ->method('save') ->willReturnSelf(); } - - $productMock->expects(static::any()) - ->method('hasDataChanges') - ->willReturn($hasDataChanges); - $productMock->expects($hasDataChanges ? static::once() : static::never()) - ->method('save') - ->willReturnSelf(); - return $productMock; } } diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js index ffabd9a8627dfca82da9b87ebd84c799086d9edf..c182d9f8216c09a42868eb487dfa06b0e718b5c7 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js @@ -391,11 +391,11 @@ define([ 'small_image': row['small_image'], image: row.image, 'thumbnail': row.thumbnail, - 'attributes': attributesText + 'attributes': attributesText, + 'was_changed': true }; product[this.canEditField] = row.editable; product[this.newProductField] = row.newProduct; - tmpArray.push(product); }, this); diff --git a/app/code/Magento/Deploy/Console/Command/DeployStaticContentCommand.php b/app/code/Magento/Deploy/Console/Command/DeployStaticContentCommand.php index 51345c2b7609cb8e39cf25fb9a4f4f202cba6f65..8a006c8154b4b97eb6d39c1d41f8363b3e4df761 100644 --- a/app/code/Magento/Deploy/Console/Command/DeployStaticContentCommand.php +++ b/app/code/Magento/Deploy/Console/Command/DeployStaticContentCommand.php @@ -3,7 +3,6 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Deploy\Console\Command; use Magento\Framework\App\Utility\Files; @@ -19,6 +18,8 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\App\State; use Magento\Deploy\Console\Command\DeployStaticOptionsInterface as Options; use Magento\Deploy\Model\DeployManager; +use Magento\Framework\App\Cache; +use Magento\Framework\App\Cache\Type\Dummy as DummyCache; /** * Deploy static content command @@ -29,7 +30,7 @@ class DeployStaticContentCommand extends Command /** * Key for dry-run option * @deprecated - * @see Magento\Deploy\Console\Command\DeployStaticOptionsInterface::DRY_RUN + * @see \Magento\Deploy\Console\Command\DeployStaticOptionsInterface::DRY_RUN */ const DRY_RUN_OPTION = 'dry-run'; @@ -87,6 +88,7 @@ class DeployStaticContentCommand extends Command * @param ObjectManagerFactory $objectManagerFactory * @param Locale $validator * @param ObjectManagerInterface $objectManager + * @throws \LogicException When the command name is empty */ public function __construct( ObjectManagerFactory $objectManagerFactory, @@ -96,6 +98,7 @@ class DeployStaticContentCommand extends Command $this->objectManagerFactory = $objectManagerFactory; $this->validator = $validator; $this->objectManager = $objectManager; + parent::__construct(); } @@ -373,6 +376,7 @@ class DeployStaticContentCommand extends Command /** * {@inheritdoc} * @throws \InvalidArgumentException + * @throws LocalizedException */ protected function execute(InputInterface $input, OutputInterface $output) { @@ -394,9 +398,9 @@ class DeployStaticContentCommand extends Command list ($deployableLanguages, $deployableAreaThemeMap, $requestedThemes) = $this->prepareDeployableEntities($filesUtil); - $output->writeln("Requested languages: " . implode(', ', $deployableLanguages)); - $output->writeln("Requested areas: " . implode(', ', array_keys($deployableAreaThemeMap))); - $output->writeln("Requested themes: " . implode(', ', $requestedThemes)); + $output->writeln('Requested languages: ' . implode(', ', $deployableLanguages)); + $output->writeln('Requested areas: ' . implode(', ', array_keys($deployableAreaThemeMap))); + $output->writeln('Requested themes: ' . implode(', ', $requestedThemes)); /** @var $deployManager DeployManager */ $deployManager = $this->objectManager->create( @@ -415,11 +419,13 @@ class DeployStaticContentCommand extends Command } } + $this->mockCache(); return $deployManager->deploy(); } /** * @param Files $filesUtil + * @throws \InvalidArgumentException * @return array * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) @@ -476,4 +482,18 @@ class DeployStaticContentCommand extends Command return [$deployableLanguages, $deployableAreaThemeMap, $requestedThemes]; } + + /** + * Mock Cache class with dummy implementation + * + * @return void + */ + private function mockCache() + { + $this->objectManager->configure([ + 'preferences' => [ + Cache::class => DummyCache::class + ] + ]); + } } diff --git a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php index 878ddf812028825267297aac958c22c14070f7b9..5a88c601e17e3c033040b082f8dfe47b83fd6a03 100644 --- a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php +++ b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php @@ -13,7 +13,8 @@ use Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend; use Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend; use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource; use Magento\Framework\App\Config\Element; -use Magento\Framework\App\ResourceConnection\Config; +use Magento\Framework\DB\Adapter\DuplicateException; +use Magento\Framework\Exception\AlreadyExistsException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Model\AbstractModel; use Magento\Framework\Model\ResourceModel\Db\ObjectRelationProcessor; @@ -1108,6 +1109,7 @@ abstract class AbstractEntity extends AbstractResource implements EntityInterfac * @param \Magento\Framework\Model\AbstractModel $object * @return $this * @throws \Exception + * @throws AlreadyExistsException */ public function save(\Magento\Framework\Model\AbstractModel $object) { @@ -1147,6 +1149,10 @@ abstract class AbstractEntity extends AbstractResource implements EntityInterfac } $this->addCommitCallback([$object, 'afterCommitCallback'])->commit(); $object->setHasDataChanges(false); + } catch (DuplicateException $e) { + $this->rollBack(); + $object->setHasDataChanges(true); + throw new AlreadyExistsException(__('Unique constraint violation found'), $e); } catch (\Exception $e) { $this->rollBack(); $object->setHasDataChanges(true); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index 4f13ee75bfe32c29ae544c19e950691ead763323..0d8d18df223767b2812f58356de3b7904090d8f7 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -6,8 +6,8 @@ namespace Magento\Eav\Model\Entity\Attribute; -use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Api\AttributeValueFactory; +use Magento\Framework\Exception\LocalizedException; /** * Entity/Attribute/Model - attribute abstract @@ -595,11 +595,10 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens { /** @var array $emptyStringTypes list of attribute types that treat empty string as a possible value */ $emptyStringTypes = ['int', 'decimal', 'datetime', 'varchar', 'text', 'static']; - $attributeType = $this->getBackend()->getType(); return (is_array($value) && count($value) == 0) || $value === null - || ($value === false && $attributeType != 'int') - || ($value === '' && in_array($attributeType, $emptyStringTypes)); + || ($value === false && $this->getBackend()->getType() != 'int') + || ($value === '' && in_array($this->getBackend()->getType(), $emptyStringTypes)); } /** diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AttributeGroupAlreadyExistsException.php b/app/code/Magento/Eav/Model/Entity/Attribute/AttributeGroupAlreadyExistsException.php new file mode 100644 index 0000000000000000000000000000000000000000..ca80ca089a2ea4cc3b297b4dc933b53049ed31f1 --- /dev/null +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AttributeGroupAlreadyExistsException.php @@ -0,0 +1,15 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Eav\Model\Entity\Attribute; + +use Magento\Framework\Exception\AlreadyExistsException; + +/** + * Class AttributeGroupAlreadyExistsException + */ +class AttributeGroupAlreadyExistsException extends AlreadyExistsException +{ +} diff --git a/app/code/Magento/Eav/Model/ResourceModel/AttributeLoader.php b/app/code/Magento/Eav/Model/ResourceModel/AttributeLoader.php new file mode 100644 index 0000000000000000000000000000000000000000..439f550a2bf020fadd8ae18abfb2348f4b18cf6b --- /dev/null +++ b/app/code/Magento/Eav/Model/ResourceModel/AttributeLoader.php @@ -0,0 +1,97 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Eav\Model\ResourceModel; + +use Magento\Eav\Api\AttributeRepositoryInterface as AttributeRepository; +use Magento\Eav\Model\Entity\AttributeCache; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\EntityManager\MetadataPool; + +/** + * Сlass responsible for loading and caching of attributes related to the given attribute set. + * + * Can be used to improve performance of services that mostly read attribute data. + */ +class AttributeLoader +{ + /** Name of ATTRIBUTE_SET_ID field */ + const ATTRIBUTE_SET_ID = 'attribute_set_id'; + + /** + * @var AttributeRepository + */ + private $attributeRepository; + + /** + * @var MetadataPool + */ + private $metadataPool; + + /** + * @var SearchCriteriaBuilder + */ + private $searchCriteriaBuilder; + + /** + * @var AttributeCache + */ + private $attributeCache; + + /** + * AttributeLoader constructor. + * @param AttributeRepository $attributeRepository + * @param MetadataPool $metadataPool + * @param SearchCriteriaBuilder $searchCriteriaBuilder + * @param AttributeCache $attributeCache + */ + public function __construct( + AttributeRepository $attributeRepository, + MetadataPool $metadataPool, + SearchCriteriaBuilder $searchCriteriaBuilder, + AttributeCache $attributeCache + ) { + $this->attributeRepository = $attributeRepository; + $this->metadataPool = $metadataPool; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; + $this->attributeCache = $attributeCache; + } + + /** + * Get attributes list from attribute set + * + * @param string $entityType + * @param int $attributeSetId + * @return \Magento\Eav\Api\Data\AttributeInterface[]|\object[] + */ + public function getAttributes($entityType, $attributeSetId = null) + { + $suffix = self::ATTRIBUTE_SET_ID . '-' . ($attributeSetId ?: 'all'); + if ($attributes = $this->attributeCache->getAttributes($entityType, $suffix)) { + return $attributes; + } + + $metadata = $this->metadataPool->getMetadata($entityType); + + if ($attributeSetId === null) { + $criteria = $this->searchCriteriaBuilder->addFilter(self::ATTRIBUTE_SET_ID, null, 'neq')->create(); + } else { + $criteria = $this->searchCriteriaBuilder->addFilter(self::ATTRIBUTE_SET_ID, $attributeSetId)->create(); + } + + $searchResult = $this->attributeRepository->getList( + $metadata->getEavEntityType(), + $criteria + ); + $attributes = $searchResult->getItems(); + + $this->attributeCache->saveAttributes( + $entityType, + $attributes, + $suffix + ); + return $attributes; + } +} diff --git a/app/code/Magento/Eav/Model/ResourceModel/AttributePersistor.php b/app/code/Magento/Eav/Model/ResourceModel/AttributePersistor.php index 74373cb593c4086c06378050e1fa89b944d78be6..5e340595df9867b1cb02fd795c6fc9be7e34fc02 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/AttributePersistor.php +++ b/app/code/Magento/Eav/Model/ResourceModel/AttributePersistor.php @@ -113,13 +113,14 @@ class AttributePersistor return; } $metadata = $this->metadataPool->getMetadata($entityType); + $linkField = $metadata->getLinkField(); foreach ($this->delete[$entityType] as $link => $data) { $attributeCodes = array_keys($data); foreach ($attributeCodes as $attributeCode) { /** @var AbstractAttribute $attribute */ $attribute = $this->attributeRepository->get($metadata->getEavEntityType(), $attributeCode); $conditions = [ - $metadata->getLinkField() . ' = ?' => $link, + $linkField . ' = ?' => $link, 'attribute_id = ?' => $attribute->getAttributeId() ]; foreach ($context as $scope) { @@ -147,6 +148,7 @@ class AttributePersistor return; } $metadata = $this->metadataPool->getMetadata($entityType); + $linkField = $metadata->getLinkField(); foreach ($this->insert[$entityType] as $link => $data) { foreach ($data as $attributeCode => $attributeValue) { /** @var AbstractAttribute $attribute */ @@ -155,7 +157,7 @@ class AttributePersistor $attributeCode ); $data = [ - $metadata->getLinkField() => $link, + $linkField => $link, 'attribute_id' => $attribute->getAttributeId(), 'value' => $this->prepareValue($entityType, $attributeValue, $attribute) ]; @@ -180,6 +182,7 @@ class AttributePersistor return; } $metadata = $this->metadataPool->getMetadata($entityType); + $linkField = $metadata->getLinkField(); foreach ($this->update[$entityType] as $link => $data) { foreach ($data as $attributeCode => $attributeValue) { /** @var AbstractAttribute $attribute */ @@ -188,7 +191,7 @@ class AttributePersistor $attributeCode ); $conditions = [ - $metadata->getLinkField() . ' = ?' => $link, + $linkField . ' = ?' => $link, 'attribute_id = ?' => $attribute->getAttributeId(), ]; foreach ($context as $scope) { diff --git a/app/code/Magento/Eav/Model/ResourceModel/CreateHandler.php b/app/code/Magento/Eav/Model/ResourceModel/CreateHandler.php index 1a8aaaf027f561966101e360020fb3a2441e27d6..df411b6a21698033c60839c0d855c3b0ed4e96e5 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/CreateHandler.php +++ b/app/code/Magento/Eav/Model/ResourceModel/CreateHandler.php @@ -6,9 +6,10 @@ namespace Magento\Eav\Model\ResourceModel; use Magento\Eav\Api\AttributeRepositoryInterface as AttributeRepository; -use Magento\Framework\EntityManager\Operation\AttributeInterface; -use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\EntityManager\MetadataPool; +use Magento\Framework\EntityManager\Operation\AttributeInterface; use Magento\Framework\Model\Entity\ScopeResolver; /** @@ -42,40 +43,43 @@ class CreateHandler implements AttributeInterface */ private $scopeResolver; + /** + * @var AttributeLoader + */ + private $attributeLoader; + /** * @param AttributeRepository $attributeRepository * @param MetadataPool $metadataPool * @param SearchCriteriaBuilder $searchCriteriaBuilder * @param AttributePersistor $attributePersistor * @param ScopeResolver $scopeResolver + * @param AttributeLoader $attributeLoader */ public function __construct( AttributeRepository $attributeRepository, MetadataPool $metadataPool, SearchCriteriaBuilder $searchCriteriaBuilder, AttributePersistor $attributePersistor, - ScopeResolver $scopeResolver + ScopeResolver $scopeResolver, + AttributeLoader $attributeLoader = null ) { $this->attributeRepository = $attributeRepository; $this->metadataPool = $metadataPool; $this->searchCriteriaBuilder = $searchCriteriaBuilder; $this->attributePersistor = $attributePersistor; $this->scopeResolver = $scopeResolver; + $this->attributeLoader = $attributeLoader ?: ObjectManager::getInstance()->get(AttributeLoader::class); } /** * @param string $entityType + * @param int $attributeSetId * @return \Magento\Eav\Api\Data\AttributeInterface[] - * @throws \Exception */ - protected function getAttributes($entityType) + protected function getAttributes($entityType, $attributeSetId = null) { - $metadata = $this->metadataPool->getMetadata($entityType); - $searchResult = $this->attributeRepository->getList( - $metadata->getEavEntityType(), - $this->searchCriteriaBuilder->addFilter('attribute_set_id', null, 'neq')->create() - ); - return $searchResult->getItems(); + return $this->attributeLoader->getAttributes($entityType, $attributeSetId); } /** @@ -92,23 +96,28 @@ class CreateHandler implements AttributeInterface $metadata = $this->metadataPool->getMetadata($entityType); if ($metadata->getEavEntityType()) { $processed = []; + $entityLinkField = $metadata->getLinkField(); + $attributeSetId = isset($entityData[AttributeLoader::ATTRIBUTE_SET_ID]) + ? $entityData[AttributeLoader::ATTRIBUTE_SET_ID] + : null; // @todo verify is it normal to not have attributer_set_id /** @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute */ - foreach ($this->getAttributes($entityType) as $attribute) { + foreach ($this->getAttributes($entityType, $attributeSetId) as $attribute) { if ($attribute->isStatic()) { continue; } - if (isset($entityData[$attribute->getAttributeCode()]) - && !is_array($entityData[$attribute->getAttributeCode()]) - && !$attribute->isValueEmpty($entityData[$attribute->getAttributeCode()]) + + $attributeCode = $attribute->getAttributeCode(); + if (isset($entityData[$attributeCode]) + && !is_array($entityData[$attributeCode]) + && !$attribute->isValueEmpty($entityData[$attributeCode]) ) { - $entityLinkField = $metadata->getLinkField(); $this->attributePersistor->registerInsert( $entityType, $entityData[$entityLinkField], - $attribute->getAttributeCode(), - $entityData[$attribute->getAttributeCode()] + $attributeCode, + $entityData[$attributeCode] ); - $processed[$attribute->getAttributeCode()] = $entityData[$attribute->getAttributeCode()]; + $processed[$attributeCode] = $entityData[$attributeCode]; } } $context = $this->scopeResolver->getEntityContext($entityType, $entityData); diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Group.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Group.php index 796f4d19f2eb8d90c4625542a33257e3a065a5af..9515bbc66437859d984f126b4d49f483c72f8194 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Group.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Group.php @@ -5,6 +5,10 @@ */ namespace Magento\Eav\Model\ResourceModel\Entity\Attribute; +use Magento\Eav\Model\Entity\Attribute\AttributeGroupAlreadyExistsException; +use Magento\Framework\DB\Adapter\DuplicateException; +use Magento\Framework\Model\AbstractModel; + /** * Eav Resource Entity Attribute Group * @@ -50,10 +54,10 @@ class Group extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb /** * Perform actions before object save * - * @param \Magento\Framework\Model\AbstractModel $object + * @param AbstractModel $object * @return \Magento\Framework\Model\ResourceModel\Db\AbstractDb */ - protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object) + protected function _beforeSave(AbstractModel $object) { if (!$object->getSortOrder()) { $object->setSortOrder($this->_getMaxSortOrder($object) + 1); @@ -64,10 +68,10 @@ class Group extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb /** * Perform actions after object save * - * @param \Magento\Framework\Model\AbstractModel $object + * @param AbstractModel $object * @return \Magento\Framework\Model\ResourceModel\Db\AbstractDb */ - protected function _afterSave(\Magento\Framework\Model\AbstractModel $object) + protected function _afterSave(AbstractModel $object) { if ($object->getAttributes()) { foreach ($object->getAttributes() as $attribute) { @@ -82,7 +86,7 @@ class Group extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb /** * Retrieve max sort order * - * @param \Magento\Framework\Model\AbstractModel $object + * @param AbstractModel $object * @return int */ protected function _getMaxSortOrder($object) @@ -130,4 +134,38 @@ class Group extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb return $this; } + + /** + * {@inheritdoc} + */ + protected function saveNewObject(AbstractModel $object) + { + try { + return parent::saveNewObject($object); + } catch (DuplicateException $e) { + throw new AttributeGroupAlreadyExistsException( + __( + 'Attribute group with same code already exist. Please rename "%1" group', + $object->getAttributeGroupName() + ) + ); + } + } + + /** + * {@inheritdoc} + */ + protected function updateObject(AbstractModel $object) + { + try { + return parent::updateObject($object); + } catch (DuplicateException $e) { + throw new AttributeGroupAlreadyExistsException( + __( + 'Attribute group with same code already exist. Please rename "%1" group', + $object->getAttributeGroupName() + ) + ); + } + } } diff --git a/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php b/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php index 0f892a272fa1a209ca7b2e632abc98db5afb5d3d..c775a24a03c465dad45640a7f634823cb8b43ef8 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php +++ b/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php @@ -54,6 +54,11 @@ class UpdateHandler implements AttributeInterface */ private $readHandler; + /** + * @var AttributeLoader + */ + private $attributeLoader; + /** * UpdateHandler constructor. * @param AttributeRepository $attributeRepository @@ -62,6 +67,7 @@ class UpdateHandler implements AttributeInterface * @param AttributePersistor $attributePersistor * @param ReadSnapshot $readSnapshot * @param ScopeResolver $scopeResolver + * @param AttributeLoader $attributeLoader */ public function __construct( AttributeRepository $attributeRepository, @@ -69,7 +75,8 @@ class UpdateHandler implements AttributeInterface SearchCriteriaBuilder $searchCriteriaBuilder, AttributePersistor $attributePersistor, ReadSnapshot $readSnapshot, - ScopeResolver $scopeResolver + ScopeResolver $scopeResolver, + AttributeLoader $attributeLoader = null ) { $this->attributeRepository = $attributeRepository; $this->metadataPool = $metadataPool; @@ -77,22 +84,17 @@ class UpdateHandler implements AttributeInterface $this->attributePersistor = $attributePersistor; $this->readSnapshot = $readSnapshot; $this->scopeResolver = $scopeResolver; + $this->attributeLoader = $attributeLoader ?: ObjectManager::getInstance()->get(AttributeLoader::class); } /** * @param string $entityType + * @param int $attributeSetId * @return \Magento\Eav\Api\Data\AttributeInterface[] - * @throws \Exception */ - protected function getAttributes($entityType) + protected function getAttributes($entityType, $attributeSetId = null) { - $metadata = $this->metadataPool->getMetadata($entityType); - - $searchResult = $this->attributeRepository->getList( - $metadata->getEavEntityType(), - $this->searchCriteriaBuilder->addFilter('attribute_set_id', null, 'neq')->create() - ); - return $searchResult->getItems(); + return $this->attributeLoader->getAttributes($entityType, $attributeSetId); } /** @@ -118,8 +120,11 @@ class UpdateHandler implements AttributeInterface $entityDataForSnapshot[$scope->getIdentifier()] = $entityData[$scope->getIdentifier()]; } } + $attributeSetId = isset($entityData[AttributeLoader::ATTRIBUTE_SET_ID]) + ? $entityData[AttributeLoader::ATTRIBUTE_SET_ID] + : null; // @todo verify is it normal to not have attributer_set_id $snapshot = $this->readSnapshot->execute($entityType, $entityDataForSnapshot); - foreach ($this->getAttributes($entityType) as $attribute) { + foreach ($this->getAttributes($entityType, $attributeSetId) as $attribute) { if ($attribute->isStatic()) { continue; } diff --git a/app/code/Magento/Eav/Setup/UpgradeSchema.php b/app/code/Magento/Eav/Setup/UpgradeSchema.php new file mode 100644 index 0000000000000000000000000000000000000000..2b52bba7c2efbd379851ddf16a0cafbc077dcaf2 --- /dev/null +++ b/app/code/Magento/Eav/Setup/UpgradeSchema.php @@ -0,0 +1,48 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Eav\Setup; + +use Magento\Framework\Setup\UpgradeSchemaInterface; +use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\Setup\SchemaSetupInterface; + +/** + * Upgrade the Eav module DB scheme + */ +class UpgradeSchema implements UpgradeSchemaInterface +{ + /** + * {@inheritdoc} + */ + public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) + { + $setup->startSetup(); + + if (version_compare($context->getVersion(), '2.1.0', '<')) { + $this->addUniqueKeyToEavAttributeGroupTable($setup); + } + $setup->endSetup(); + } + + /** + * @param SchemaSetupInterface $setup + * @return void + */ + private function addUniqueKeyToEavAttributeGroupTable(SchemaSetupInterface $setup) + { + $setup->getConnection()->addIndex( + $setup->getTable('eav_attribute_group'), + $setup->getIdxName( + 'catalog_category_product', + ['attribute_set_id', 'attribute_group_code'], + \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE + ), + ['attribute_set_id', 'attribute_group_code'], + \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE + ); + } +} diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractEntityTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractEntityTest.php index f39eeb892757645df9fc3157894249e18d8c4803..7628207e25a52c2ea7cd595bd47f65fb0d18ef81 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractEntityTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractEntityTest.php @@ -5,13 +5,17 @@ */ namespace Magento\Eav\Test\Unit\Model\Entity; +use Magento\Eav\Model\Entity\AbstractEntity; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\DB\Adapter\DuplicateException; +use Magento\Framework\Model\AbstractModel; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; class AbstractEntityTest extends \PHPUnit_Framework_TestCase { /** * Entity model to be tested - * @var \Magento\Eav\Model\Entity\AbstractEntity|\PHPUnit_Framework_MockObject_MockObject + * @var AbstractEntity|\PHPUnit_Framework_MockObject_MockObject */ protected $_model; @@ -23,11 +27,11 @@ class AbstractEntityTest extends \PHPUnit_Framework_TestCase $objectManager = new ObjectManager($this); $this->eavConfig = $this->getMock(\Magento\Eav\Model\Config::class, [], [], '', false); $arguments = $objectManager->getConstructArguments( - \Magento\Eav\Model\Entity\AbstractEntity::class, + AbstractEntity::class, ['eavConfig' => $this->eavConfig] ); $this->_model = $this->getMockForAbstractClass( - \Magento\Eav\Model\Entity\AbstractEntity::class, + AbstractEntity::class, $arguments ); } @@ -113,7 +117,7 @@ class AbstractEntityTest extends \PHPUnit_Framework_TestCase /** * Get adapter mock * - * @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\DB\Adapter\AdapterInterface + * @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\DB\Adapter\Pdo\Mysql */ protected function _getConnectionMock() { @@ -300,7 +304,7 @@ class AbstractEntityTest extends \PHPUnit_Framework_TestCase $objectManager = new ObjectManager($this); $this->eavConfig = $this->getMock(\Magento\Eav\Model\Config::class, [], [], '', false); $arguments = $objectManager->getConstructArguments( - \Magento\Eav\Model\Entity\AbstractEntity::class, + AbstractEntity::class, [ 'eavConfig' => $eavConfig, 'data' => [ @@ -310,8 +314,8 @@ class AbstractEntityTest extends \PHPUnit_Framework_TestCase ] ] ); - /** @var $model \Magento\Framework\Model\AbstractModel|\PHPUnit_Framework_MockObject_MockObject */ - $model = $this->getMockBuilder(\Magento\Eav\Model\Entity\AbstractEntity::class) + /** @var $model AbstractEntity|\PHPUnit_Framework_MockObject_MockObject */ + $model = $this->getMockBuilder(AbstractEntity::class) ->setConstructorArgs($arguments) ->setMethods(['_getValue', 'beginTransaction', 'commit', 'rollback', 'getConnection']) ->getMock(); @@ -353,4 +357,30 @@ class AbstractEntityTest extends \PHPUnit_Framework_TestCase ] ]; } + + /** + * @expectedException \Magento\Framework\Exception\AlreadyExistsException + */ + public function testDuplicateExceptionProcessingOnSave() + { + $connection = $this->getMock(AdapterInterface::class); + $connection->expects($this->once())->method('rollback'); + + /** @var AbstractEntity|\PHPUnit_Framework_MockObject_MockObject $model */ + $model = $this->getMockBuilder(AbstractEntity::class) + ->disableOriginalConstructor() + ->setMethods(['getConnection']) + ->getMockForAbstractClass(); + $model->expects($this->any())->method('getConnection')->willReturn($connection); + + /** @var AbstractModel|\PHPUnit_Framework_MockObject_MockObject $object */ + $object = $this->getMockBuilder(AbstractModel::class) + ->disableOriginalConstructor() + ->getMock(); + $object->expects($this->once())->method('hasDataChanges')->willReturn(true); + $object->expects($this->once())->method('beforeSave')->willThrowException(new DuplicateException()); + $object->expects($this->once())->method('setHasDataChanges')->with(true); + + $model->save($object); + } } diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php index d6b88e0ac56915c3b116ac740b18cfd31ae9f876..a10bafacda42dc2b72fcc285307a0250cae3074b 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php @@ -207,7 +207,7 @@ class AbstractAttributeTest extends \PHPUnit_Framework_TestCase ] ); $backendModelMock->expects($this->any())->method('getType')->willReturn($attributeType); - $model->expects($this->once())->method('getBackend')->willReturn($backendModelMock); + $model->expects($this->any())->method('getBackend')->willReturn($backendModelMock); $this->assertEquals($isEmpty, $model->isValueEmpty($value)); } diff --git a/app/code/Magento/Eav/etc/module.xml b/app/code/Magento/Eav/etc/module.xml index c1c313d91501989578f03b404ae91acc2d0ccbb1..d03606d1eeb900a1dfec428c172cba0b47a01fc0 100644 --- a/app/code/Magento/Eav/etc/module.xml +++ b/app/code/Magento/Eav/etc/module.xml @@ -6,7 +6,7 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_Eav" setup_version="2.0.0"> + <module name="Magento_Eav" setup_version="2.1.0"> <sequence> <module name="Magento_Store"/> </sequence> diff --git a/app/code/Magento/ImportExport/Block/Adminhtml/Export/Edit/Form.php b/app/code/Magento/ImportExport/Block/Adminhtml/Export/Edit/Form.php index a56642d1dda33952bdb8d238dc074428a170b54b..fec1684f39f36ca7e259863bba817119cc896054 100644 --- a/app/code/Magento/ImportExport/Block/Adminhtml/Export/Edit/Form.php +++ b/app/code/Magento/ImportExport/Block/Adminhtml/Export/Edit/Form.php @@ -86,6 +86,16 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic 'values' => $this->_formatFactory->create()->toOptionArray() ] ); + $fieldset->addField( + \Magento\ImportExport\Model\Export::FIELDS_ENCLOSURE, + 'checkbox', + [ + 'name' => \Magento\ImportExport\Model\Export::FIELDS_ENCLOSURE, + 'label' => __('Fields Enclosure'), + 'title' => __('Fields Enclosure'), + 'value' => 1, + ] + ); $form->setUseContainer(true); $this->setForm($form); diff --git a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php index 1511f58d4b039c5376ef293b8c011d4e2b0e7396..435a663923306da40741c2c9a43a6a234944a98a 100644 --- a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php +++ b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php @@ -174,6 +174,16 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic 'value' => Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, ] ); + $fieldsets[$behaviorCode]->addField( + $behaviorCode . \Magento\ImportExport\Model\Import::FIELDS_ENCLOSURE, + 'checkbox', + [ + 'name' => \Magento\ImportExport\Model\Import::FIELDS_ENCLOSURE, + 'label' => __('Fields enclosure'), + 'title' => __('Fields enclosure'), + 'value' => 1, + ] + ); } // fieldset for file uploading diff --git a/app/code/Magento/ImportExport/Model/Export.php b/app/code/Magento/ImportExport/Model/Export.php index 2785327326e89359c6aabbbedb4e38cb136c1dfa..3b833cd4ab8834fc07a86ef9a52b51d66140ea3a 100644 --- a/app/code/Magento/ImportExport/Model/Export.php +++ b/app/code/Magento/ImportExport/Model/Export.php @@ -20,6 +20,11 @@ class Export extends \Magento\ImportExport\Model\AbstractModel const FILTER_ELEMENT_SKIP = 'skip_attr'; + /** + * Allow multiple values wrapping in double quotes for additional attributes. + */ + const FIELDS_ENCLOSURE = 'fields_enclosure'; + /** * Filter fields types. */ diff --git a/app/code/Magento/ImportExport/Model/Import.php b/app/code/Magento/ImportExport/Model/Import.php index 157887ec62c526458377d5d0103a992fab60a63d..89b5f88f0e9c2d4e071cdc0ec46d97bf731e64e8 100644 --- a/app/code/Magento/ImportExport/Model/Import.php +++ b/app/code/Magento/ImportExport/Model/Import.php @@ -78,6 +78,11 @@ class Import extends \Magento\ImportExport\Model\AbstractModel */ const FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR = '_import_multiple_value_separator'; + /** + * Allow multiple values wrapping in double quotes for additional attributes. + */ + const FIELDS_ENCLOSURE = 'fields_enclosure'; + /**#@-*/ /** diff --git a/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/before.phtml b/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/before.phtml index b8acac6a1ab64dbec581785293c16ad18c5218f2..ce4f61cef4febc90a3e802c7dacc9b2e09fb28c3 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/before.phtml +++ b/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/before.phtml @@ -80,6 +80,9 @@ require([ var oldAction = form.action; var url = oldAction + ((oldAction.slice(-1) != '/') ? '/' : '') + 'entity/' + $F('entity') + '/file_format/' + $F('file_format'); + if ($F('fields_enclosure')) { + url += '/fields_enclosure/' + $F('fields_enclosure'); + } form.action = url; form.submit(); form.action = oldAction; diff --git a/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js b/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js index d87b6b6b665ca0d070287474edb41eb5ced41c33..dca12f832cd15e1cdc197ec909df92557c45da60 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js @@ -79,6 +79,10 @@ define([ getData: function (params, options) { var cachedRequest = this.getRequest(params); + if (params && params.filters && params.filters['store_id']) { + cachedRequest = false; + } + options = options || {}; return !options.refresh && cachedRequest ? diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/Annotation/ApiDataFixture.php b/dev/tests/api-functional/framework/Magento/TestFramework/Annotation/ApiDataFixture.php index 5eeb7ddb61fa05657b08dda4711e82938e8778ce..0ad53eeeb90d9dab3a8877624429efefe314aefd 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/Annotation/ApiDataFixture.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/Annotation/ApiDataFixture.php @@ -51,6 +51,7 @@ class ApiDataFixture */ public function startTest(\PHPUnit_Framework_TestCase $test) { + \Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize(); /** Apply method level fixtures if thy are available, apply class level fixtures otherwise */ $this->_applyFixtures($this->_getFixtures('method', $test) ?: $this->_getFixtures('class', $test)); } @@ -61,6 +62,9 @@ class ApiDataFixture public function endTest() { $this->_revertFixtures(); + /** @var $objectManager \Magento\TestFramework\ObjectManager */ + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $objectManager->get(\Magento\Eav\Model\Entity\AttributeCache::class)->clear(); } /** diff --git a/dev/tests/functional/tests/app/Magento/Authorizenet/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Authorizenet/Test/TestCase/OnePageCheckoutTest.xml index c949d827b4879599685bca266e12edfd2eb3a384..d4cf5dab742aa37684e8b5ee884bd6164c88426f 100644 --- a/dev/tests/functional/tests/app/Magento/Authorizenet/Test/TestCase/OnePageCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Authorizenet/Test/TestCase/OnePageCheckoutTest.xml @@ -6,12 +6,12 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> - <testCase name="Magento\Checkout\Test\TestCase\OnePageCheckoutTest" summary="One page check out with Authorize.Net payment method."> - <variation name="OnePageCheckoutAuthorizenetTestVariation1" summary="Check Out as a Guest with Authorize.Net and Offline Shipping method" ticketId="MAGETWO-12832"> + <testCase name="Magento\Checkout\Test\TestCase\OnePageCheckoutTest" summary="One page check out with Authorize.Net Direct Post payment method."> + <variation name="OnePageCheckoutAuthorizenetTestVariation1" summary="CheckOut with Authorize.Net Direct Post" ticketId="MAGETWO-59170"> <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> <data name="customer/dataset" xsi:type="string">default</data> - <data name="shippingAddress/dataset" xsi:type="string">US_address_1</data> - <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="checkoutMethod" xsi:type="string">login</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data> <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> <data name="shipping/shipping_method" xsi:type="string">Fixed</data> <data name="prices" xsi:type="array"> @@ -26,7 +26,7 @@ <item name="isClosed" xsi:type="string">No</item> <item name="transactionType" xsi:type="string">Authorization</item> </data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/BraintreeSettlementReportTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/BraintreeSettlementReportTest.php index 6601bd44892c93e30573c5342e483eb232573e70..dda155f7fd66bd33a5532ab4a36c937a1d10178b 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/BraintreeSettlementReportTest.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/BraintreeSettlementReportTest.php @@ -38,6 +38,7 @@ class BraintreeSettlementReportTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S1'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/BraintreeSettlementReportTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/BraintreeSettlementReportTest.xml index 183dc6ac906074fb6dc918e765d648ea437fd05b..e80f6071ae5d1d33b37bb7c26c7389ed08aa8962 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/BraintreeSettlementReportTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/BraintreeSettlementReportTest.xml @@ -22,7 +22,7 @@ <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> <data name="configData" xsi:type="string">braintree</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test, test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalCartTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalCartTest.php index a0bf482705f552318a7cdd09951aaff14eaf1cb2..c9d0904c85d675d7a4aa360ac6a2f8c00c6b0862 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalCartTest.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalCartTest.php @@ -33,6 +33,7 @@ class CheckoutWithBraintreePaypalCartTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalCartTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalCartTest.xml index 09b33bfa79958668ceef14a20e48cf0ecce2646e..9e1090d6a22f91102be14f0f4319921651f01841 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalCartTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalCartTest.xml @@ -20,7 +20,7 @@ <data name="payment/method" xsi:type="string">braintree_paypal</data> <data name="configData" xsi:type="string">braintree, braintree_paypal, braintree_paypal_skip_order_review</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> @@ -42,7 +42,7 @@ <data name="payment/method" xsi:type="string">braintree_paypal</data> <data name="configData" xsi:type="string">braintree, braintree_paypal, braintree_paypal_sale, braintree_paypal_skip_order_review</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalMinicartTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalMinicartTest.php index f0f0291b33e20428765c110dbb23600ba463bdde..9ee6bfb7c4e29b84043fd3b116a09153bfab4233 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalMinicartTest.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalMinicartTest.php @@ -33,6 +33,7 @@ class CheckoutWithBraintreePaypalMinicartTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalMinicartTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalMinicartTest.xml index b426e7578729dd3b0ba514440b7b425b373ae20b..b41ea91e4598255a67e3e44180895873358a9b1a 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalMinicartTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CheckoutWithBraintreePaypalMinicartTest.xml @@ -20,7 +20,7 @@ <data name="payment/method" xsi:type="string">braintree_paypal</data> <data name="configData" xsi:type="string">braintree, braintree_paypal, braintree_paypal_skip_order_review</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> @@ -42,7 +42,7 @@ <data name="payment/method" xsi:type="string">braintree_paypal</data> <data name="configData" xsi:type="string">braintree, braintree_paypal, braintree_paypal_sale, braintree_paypal_skip_order_review</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineCreditMemoBraintreePaypalTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineCreditMemoBraintreePaypalTest.php index 6554845d5ff81af96b887a9dbcb8e05761b21463..9e6cf0991db4e5fb2c3dd2c45de7d365e67395f6 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineCreditMemoBraintreePaypalTest.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineCreditMemoBraintreePaypalTest.php @@ -25,6 +25,7 @@ class CreateOnlineCreditMemoBraintreePaypalTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S1'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineCreditMemoBraintreePaypalTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineCreditMemoBraintreePaypalTest.xml index 56c33af7a82b986b23372c9cbf0f2e8e915876a3..53847e55fd9f91e29fbeeb6c71a0402a1fb6a6f6 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineCreditMemoBraintreePaypalTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineCreditMemoBraintreePaypalTest.xml @@ -22,9 +22,8 @@ <data name="payment/method" xsi:type="string">braintree_paypal</data> <data name="configData" xsi:type="string">braintree, braintree_paypal, braintree_paypal_sale, braintree_paypal_skip_order_review</data> <data name="paymentAction" xsi:type="string">sale</data> - <data name="orderButtonsAvailable" xsi:type="string">Back, Send Email, Credit Memo, Hold, Ship, Reorder</data> <data name="data/items_data/0/qty" xsi:type="string">-</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Sales\Test\Constraint\AssertRefundSuccessCreateMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertRefundInCreditMemoTab" /> <constraint name="Magento\Sales\Test\Constraint\AssertRefundInCommentsHistory" /> @@ -42,12 +41,11 @@ <data name="shipping/shipping_method" xsi:type="string">Fixed</data> <data name="payment/method" xsi:type="string">braintree_paypal</data> <data name="configData" xsi:type="string">braintree, braintree_paypal, braintree_paypal_skip_order_review</data> - <data name="orderButtonsAvailable" xsi:type="string">Back, Send Email, Credit Memo, Hold, Ship, Reorder</data> <data name="data/items_data/0/qty" xsi:type="string">2</data> <data name="refundData/items_data/0/qty" xsi:type="string">1</data> <data name="order/dataset" xsi:type="string">default</data> <data name="isCreditMemoPartial" xsi:type="string">Yes</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Sales\Test\Constraint\AssertRefundSuccessCreateMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertRefundInCreditMemoTab" /> <constraint name="Magento\Sales\Test\Constraint\AssertRefundInCommentsHistory" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineInvoiceEntityTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineInvoiceEntityTest.xml index 702a732e937eabedff8f6525e651fe4c16de942c..d9f382e4b650e5ce48955e264c67b36c893dbb84 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineInvoiceEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineInvoiceEntityTest.xml @@ -29,7 +29,7 @@ <data name="data/items_data/0/qty" xsi:type="string">-</data> <data name="data/form_data/do_shipment" xsi:type="string">No</data> <data name="data/form_data/comment_text" xsi:type="string">comments</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceSuccessCreateMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderButtonsAvailable" /> <constraint name="Magento\Sales\Test\Constraint\AssertCaptureInCommentsHistory" /> @@ -58,7 +58,7 @@ <data name="data/items_data/0/qty" xsi:type="string">1</data> <data name="data/form_data/do_shipment" xsi:type="string">No</data> <data name="data/form_data/comment_text" xsi:type="string">comments</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceSuccessCreateMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderButtonsAvailable" /> <constraint name="Magento\Sales\Test\Constraint\AssertCaptureInCommentsHistory" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml index 80596fb577b970d41e01e8e98d26c86a28262b70..9614923691c6c097702c3a222bfc52edfcd2489a 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Sales\Test\TestCase\CreateOrderBackendTest" summary="Checkout with Braintree Credit Card from Admin"> <variation name="CreateOrderBackendTestBraintreeVariation1" summary="Checkout with Braintree Credit Card from Admin (Payment Action = Authorize Only)" ticketId="MAGETWO-46294"> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> <data name="products/1" xsi:type="string">configurableProduct::with_one_option</data> <data name="products/2" xsi:type="string">bundleProduct::bundle_fixed_100_dollar_product</data> @@ -32,11 +32,10 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> <constraint name="Magento\Sales\Test\Constraint\AssertAuthorizationInCommentsHistory" /> - <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGrid" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" /> </variation> <variation name="CreateOrderBackendTestBraintreeVariation2" summary="Checkout with Braintree Credit Card from Admin (Payment Action = Authorize and Capture)" ticketId="MAGETWO-38316"> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test, test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, test_type:3rd_party_test, severity:S0</data> <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> <data name="products/1" xsi:type="string">configurableProduct::with_one_option</data> <data name="products/2" xsi:type="string">bundleProduct::bundle_fixed_100_dollar_product</data> @@ -63,7 +62,6 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> <constraint name="Magento\Sales\Test\Constraint\AssertCaptureInCommentsHistory" /> - <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGrid" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" /> </variation> </testCase> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateVaultOrderBackendTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateVaultOrderBackendTest.xml index 4f05723609c2a8305f68a6893787684ae2e3d9df..db6cd3572eaa2acec5ded94997b1951c744e6652 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateVaultOrderBackendTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateVaultOrderBackendTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Vault\Test\TestCase\CreateVaultOrderBackendTest" summary="Create Order from Admin via Braintree with saving Credit Cards"> <variation name="CreateVaultOrderBackendTestBraintreeVariation1" summary="Checkout with Braintree Credit Card from Admin (Payment Action = Authorize Only)" ticketId="MAGETWO-47137, MAGETWO-47139"> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> <data name="customer/dataset" xsi:type="string">default</data> <data name="billingAddress/dataset" xsi:type="string">US_address_1_without_email</data> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePayPalBraintreeTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePayPalBraintreeTest.php index 7048984886582f7e74ffaa6d5d0597ee4ae5b018..062de338d8921e15b786de0fd4b656e824354d80 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePayPalBraintreeTest.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePayPalBraintreeTest.php @@ -29,6 +29,7 @@ class InvoicePayPalBraintreeTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S1'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePaypalBraintreeTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePaypalBraintreeTest.xml index bae626a427818b115d897d06dd33b4a894da1cba..352e0ed684919a43df66b429d5b8250d90cae351 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePaypalBraintreeTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePaypalBraintreeTest.xml @@ -26,7 +26,7 @@ <data name="data/items_data/0/qty" xsi:type="string">-</data> <data name="data/form_data/do_shipment" xsi:type="string">No</data> <data name="data/form_data/comment_text" xsi:type="string">comments</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceSuccessCreateMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderButtonsAvailable" /> <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceItems" /> @@ -51,7 +51,7 @@ <data name="data/items_data/0/qty" xsi:type="string">1</data> <data name="data/form_data/do_shipment" xsi:type="string">No</data> <data name="data/form_data/comment_text" xsi:type="string">comments</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceSuccessCreateMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderButtonsAvailable" /> <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceItems" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutAcceptPaymentTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutAcceptPaymentTest.php index 41f637d52941d463223e1706e1175939e8c817ee..68d36f3c754cf6ff5bca786cb314fd89e51f9c5d 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutAcceptPaymentTest.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutAcceptPaymentTest.php @@ -8,17 +8,25 @@ namespace Magento\Braintree\Test\TestCase; use Magento\Mtf\TestCase\Scenario; /** - * Class OnePageCheckoutAcceptPaymentTest + * Preconditions: + * 1. Order is placed with Braintree Credit Card from Storefront with Advanced Fraud Protection. * - * This scenario places order via Braintree payment with - * enabled Advanced Fraud protection and accept payment for placed order - * to future processing + * Steps: + * 1. Log in to Admin. + * 2. Go to Sales > Orders page. + * 3. Open the placed order. + * 4. Click Accept button. + * 5. Perform assertions. + * + * @group Braintree + * @ZephyrId MAGETWO-56023 */ class OnePageCheckoutAcceptPaymentTest extends Scenario { /* tags */ const MVP = 'yes'; const TEST_TYPE = 'acceptance_test, 3rd_party_test'; + const SEVERITY = 'S2'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutAcceptPaymentTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutAcceptPaymentTest.xml index f42054b4a07325512db19b497627d0099dbc7a3a..841145d7a5fdfaa92f1a82ac00c9bf51f0601643 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutAcceptPaymentTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutAcceptPaymentTest.xml @@ -21,7 +21,7 @@ <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> <data name="configData" xsi:type="string">braintree,braintree_fraudprotection</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S2</data> <constraint name="Magento\Sales\Test\Constraint\AssertAcceptPaymentSuccessMessagePresent" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> <constraint name="Magento\Sales\Test\Constraint\AssertAcceptPaymentMessageInCommentsHistory" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDenyPaymentTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDenyPaymentTest.php index 69fd4a8323eca15728d9c6f5b65c91a4929dc562..143ecb5a65d7d4a6af6a9b00d4b15175230cd0f4 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDenyPaymentTest.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDenyPaymentTest.php @@ -8,16 +8,25 @@ namespace Magento\Braintree\Test\TestCase; use Magento\Mtf\TestCase\Scenario; /** - * Class OnePageCheckoutDenyPaymentTest + * Preconditions: + * 1. Order is placed with Braintree Credit Card from Storefront with Advanced Fraud Protection. * - * This scenario places order via Braintree payment with - * enabled Advanced Fraud protection and deny payment for placed order + * Steps: + * 1. Log in to Admin. + * 2. Go to Sales > Orders page. + * 3. Open the placed order. + * 4. Click Deny button. + * 5. Perform assertions. + * + * @group Braintree + * @ZephyrId MAGETWO-56024 */ class OnePageCheckoutDenyPaymentTest extends Scenario { /* tags */ const MVP = 'yes'; const TEST_TYPE = 'acceptance_test, 3rd_party_test'; + const SEVERITY = 'S2'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDenyPaymentTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDenyPaymentTest.xml index 45476abfdfd12c18dc8a7b36782bc0b8f30ed3c0..95d07079ef36c9ae66672ec8cc465325273ecda4 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDenyPaymentTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDenyPaymentTest.xml @@ -21,7 +21,7 @@ <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> <data name="configData" xsi:type="string">braintree,braintree_fraudprotection</data> <data name="status" xsi:type="string">Canceled</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S2</data> <constraint name="Magento\Sales\Test\Constraint\AssertDenyPaymentSuccessMessagePresent" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> <constraint name="Magento\Sales\Test\Constraint\AssertDenyPaymentMessageInCommentsHistory" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml index a1ceaa53da045345a1e4a7a5a51089a5623a85b8..1e9c539c8c0d379d6e5b69929e9270b21a8cc593 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml @@ -25,7 +25,7 @@ <data name="creditCard/dataset" xsi:type="string">visa_braintree_3dsecure</data> <data name="configData" xsi:type="string">braintree, braintree_3d_secure_not_triggered_due_threshold</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> @@ -48,7 +48,7 @@ <data name="creditCard/dataset" xsi:type="string">visa_braintree_3dsecure</data> <data name="configData" xsi:type="string">braintree, braintree_3d_secure_uk</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> @@ -71,13 +71,13 @@ <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> <data name="configData" xsi:type="string">braintree</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test, test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> <constraint name="Magento\Sales\Test\Constraint\AssertAuthorizationInCommentsHistory" /> </variation> - <variation name="OnePageCheckoutBraintreeTestVariation4" summary="Checkout with Braintree for payment action Authorize and Capture" ticketId="MAGETWO-38420"> + <variation name="OnePageCheckoutBraintreeTestVariation4" summary="Checkout with Braintree for payment action Authorize and Capture" ticketId="MAGETWO-59403"> <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> <data name="products/1" xsi:type="string">configurableProduct::with_one_option</data> <data name="products/2" xsi:type="string">bundleProduct::bundle_fixed_100_dollar_product</data> @@ -98,7 +98,7 @@ <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> <data name="configData" xsi:type="string">braintree, braintree_sale</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.php index 32599aa090651c76f7d9d2663309ea3a219f79f6..e4b7d82094db5a615b3df3000f18fbd9a1f41b6d 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.php @@ -39,6 +39,7 @@ class OnePageCheckoutWith3dSecureTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S1'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.xml index 4cb5b1702dd3baac27c41b3c7367456299e8ef8e..295a9dcd5c5332dce7d6e5fad9dfcdc6f5352596 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.xml @@ -31,7 +31,7 @@ <data name="secure3d/dataset" xsi:type="string">secure3d_braintree</data> <data name="configData" xsi:type="string">braintree, braintree_3d_secure</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithBraintreePaypalTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithBraintreePaypalTest.php index 9cf0e9c90c1215649e50e0a708bcae5db371d9fd..a984f666c435680c68b97d0481b8b86a3f487b0e 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithBraintreePaypalTest.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithBraintreePaypalTest.php @@ -37,6 +37,7 @@ class OnePageCheckoutWithBraintreePaypalTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithBraintreePaypalTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithBraintreePaypalTest.xml index 8f2177209f37b7f83d2b5ad97e2599ed7f7ff67c..7e38e6f0303b64e55ce6e126a2653f0ce7420df7 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithBraintreePaypalTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithBraintreePaypalTest.xml @@ -21,7 +21,7 @@ <data name="payment/method" xsi:type="string">braintree_paypal</data> <data name="configData" xsi:type="string">braintree, braintree_paypal, braintree_paypal_skip_order_review</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> @@ -44,7 +44,7 @@ <data name="payment/method" xsi:type="string">braintree_paypal</data> <data name="configData" xsi:type="string">braintree, braintree_paypal, braintree_paypal_sale, braintree_paypal_skip_order_review</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithDiscountTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithDiscountTest.xml index 89d67936ab0c610cd67054d428c39cd8da341b53..23fc729edb99f9645f7587d8e350464c81083fcd 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithDiscountTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithDiscountTest.xml @@ -25,12 +25,10 @@ <data name="creditCardSave" xsi:type="string">Yes</data> <data name="configData" xsi:type="string">braintree, braintree_use_vault</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> - <data name="orderButtonsAvailable" xsi:type="string">Back, Cancel, Send Email, Hold, Invoice, Ship, Reorder, Edit</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> - <constraint name="Magento\Sales\Test\Constraint\AssertOrderButtonsAvailable" /> </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml index 88ab2ef65c9a0e75d2eafff8c53fe898d9504efe..5a99c4a89a313392cdd596891712b1d2d4bbaec3 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml @@ -23,7 +23,7 @@ <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> <data name="configData" xsi:type="string">braintree, braintree_use_vault</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Sales\Test\Constraint\AssertOrderSuccessCreateMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> <constraint name="Magento\Sales\Test\Constraint\AssertAuthorizationInCommentsHistory" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/SaveUseDeleteVaultForPaypalBraintreeTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/SaveUseDeleteVaultForPaypalBraintreeTest.php index f6813b74e40d7b09edf48369f6dc79ca28fefa7d..8845f2a78629da6d2c3994b1e691cce117efa8bc 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/SaveUseDeleteVaultForPaypalBraintreeTest.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/SaveUseDeleteVaultForPaypalBraintreeTest.php @@ -43,6 +43,7 @@ class SaveUseDeleteVaultForPaypalBraintreeTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/SaveUseDeleteVaultForPaypalBraintreeTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/SaveUseDeleteVaultForPaypalBraintreeTest.xml index 6e214d4c205aacc72fa8b93cbd4c082d2d02fa96..c7a5182a1dfb3d693dc03eb5c77d9d2c26622a58 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/SaveUseDeleteVaultForPaypalBraintreeTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/SaveUseDeleteVaultForPaypalBraintreeTest.xml @@ -23,7 +23,7 @@ <data name="creditCardSave" xsi:type="string">Yes</data> <data name="configData" xsi:type="string">braintree, braintree_paypal, braintree_paypal_use_vault</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Vault\Test\Constraint\AssertStoredPaymentDeletedMessage" /> </variation> </testCase> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultOnCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultOnCheckoutTest.xml index 00eb9c4802db6216bd1dbc0202231612166b306c..35d55784b676236d808cf0f54fc969fc65193b0b 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultOnCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultOnCheckoutTest.xml @@ -22,7 +22,7 @@ <data name="creditCardSave" xsi:type="string">Yes</data> <data name="configData" xsi:type="string">braintree, braintree_use_vault</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <data name="orderButtonsAvailable" xsi:type="string">Back, Cancel, Send Email, Hold, Invoice, Ship, Reorder, Edit</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultWith3dSecureOnCheckoutTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultWith3dSecureOnCheckoutTest.php index 13b8240d4c49ebe4b047e59f6bfdb63102fbcf47..d2723a300285df0b560ece526e463b495f201d8f 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultWith3dSecureOnCheckoutTest.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultWith3dSecureOnCheckoutTest.php @@ -43,6 +43,7 @@ class UseVaultWith3dSecureOnCheckoutTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S1'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultWith3dSecureOnCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultWith3dSecureOnCheckoutTest.xml index 0f00ff93612b8b1ef7792971b38846efbe3d2b43..a5aa7645148e158ad62a174bc26d08abfd037192 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultWith3dSecureOnCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultWith3dSecureOnCheckoutTest.xml @@ -27,7 +27,7 @@ <data name="creditCardSave" xsi:type="string">Yes</data> <data name="configData" xsi:type="string">braintree, braintree_use_vault, braintree_3d_secure</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <data name="orderButtonsAvailable" xsi:type="string">Back, Cancel, Send Email, Hold, Invoice, Ship</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/di.xml index be2d771e47f5bfaf9c93ac9ac909d87ef723bff1..7bdfca2f713f20a9f41b4c19d9bb1e36f55a59c1 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/di.xml @@ -8,12 +8,12 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Braintree\Test\Constraint\Assert3dSecureInfoIsPresent"> <arguments> - <argument name="severity" xsi:type="string">high</argument> + <argument name="severity" xsi:type="string">S1</argument> </arguments> </type> <type name="Magento\Braintree\Test\Constraint\AssertTransactionIsPresentInSettlementReport"> <arguments> - <argument name="severity" xsi:type="string">high</argument> + <argument name="severity" xsi:type="string">S1</argument> </arguments> </type> </config> diff --git a/dev/tests/functional/tests/app/Magento/Dhl/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Dhl/Test/TestCase/OnePageCheckoutTest.xml index 7d4a961b7686733323d2683ef335c72223f6b460..9bec14fd9575d945218bffd258cde0d06b766d92 100644 --- a/dev/tests/functional/tests/app/Magento/Dhl/Test/TestCase/OnePageCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Dhl/Test/TestCase/OnePageCheckoutTest.xml @@ -20,7 +20,7 @@ <data name="cart/data/shipping_method" xsi:type="string">Express easy</data> <data name="payment/method" xsi:type="string">checkmo</data> <data name="configData" xsi:type="string">checkmo, dhl_eu, shipping_origin_CH, config_base_currency_ch</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGrid" /> diff --git a/dev/tests/functional/tests/app/Magento/Fedex/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Fedex/Test/TestCase/OnePageCheckoutTest.xml index 9d6b7d119e09ce6f65529c028b24e190d0f8d42f..fcf8331d18ba7fd02427602013b1674aadfb11fd 100644 --- a/dev/tests/functional/tests/app/Magento/Fedex/Test/TestCase/OnePageCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Fedex/Test/TestCase/OnePageCheckoutTest.xml @@ -20,7 +20,7 @@ <data name="cart/data/shipping_method" xsi:type="string">International Economy</data> <data name="payment/method" xsi:type="string">checkmo</data> <data name="configData" xsi:type="string">checkmo, fedex, shipping_origin_US_CA</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGrid" /> @@ -39,7 +39,7 @@ <data name="cart/data/shipping_method" xsi:type="string">Ground</data> <data name="payment/method" xsi:type="string">checkmo</data> <data name="configData" xsi:type="string">checkmo, fedex, shipping_origin_US_CA</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGrid" /> diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/TestCase/ConflictResolutionTest.php b/dev/tests/functional/tests/app/Magento/Payment/Test/TestCase/ConflictResolutionTest.php index b1c2d71a43bdd7d77cabb00d010261245b599d00..37d85bd91b1d68ddea5ae0c1fd250547810d6d19 100644 --- a/dev/tests/functional/tests/app/Magento/Payment/Test/TestCase/ConflictResolutionTest.php +++ b/dev/tests/functional/tests/app/Magento/Payment/Test/TestCase/ConflictResolutionTest.php @@ -16,6 +16,7 @@ class ConflictResolutionTest extends Scenario /* tags */ const MVP = 'no'; const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S2'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/TestCase/ConflictResolutionTest.xml b/dev/tests/functional/tests/app/Magento/Payment/Test/TestCase/ConflictResolutionTest.xml index dc2ba760025fb71427e2ea50a7e3cce4e1c305e5..163c33f7306bac0f8d859ea9cddbf98e6e2eb2a3 100644 --- a/dev/tests/functional/tests/app/Magento/Payment/Test/TestCase/ConflictResolutionTest.xml +++ b/dev/tests/functional/tests/app/Magento/Payment/Test/TestCase/ConflictResolutionTest.xml @@ -40,7 +40,7 @@ <item name="Authorize.net Direct Post" xsi:type="string"/> </item> </data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S2</data> </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Payment/Test/etc/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..fc6a35a7c52c1b91792252cf08d13ff20d50a88f --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Payment/Test/etc/di.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\Payment\Test\Constraint\AssertCardRequiredFields"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Payment\Test\Constraint\AssertFieldsAreActive"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Payment\Test\Constraint\AssertFieldsAreDisabled"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Payment\Test\Constraint\AssertFieldsAreEnabled"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Payment\Test\Constraint\AssertFieldsArePresent"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.php index d4ec11acd51bf53c38de3be6e927b8a24037c1d8..3e510ab12ec3219a10ccabf6d20c0e2e8e70e0ba 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.php +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.php @@ -35,6 +35,7 @@ class CreatePayFlowOrderBackendNegativeTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S2'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.xml index 04b34813e59ceacd332657d66366d2789f469e71..4ad751de68a71f0330aa547bf74481c3e306f379 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Paypal\Test\TestCase\CreatePayFlowOrderBackendNegativeTest" summary="Verify required fields validation for PayPal Payflow Pro credit card on admin order creation" ticketId="MAGETWO-58934"> <variation name="CreatePayFlowOrderBackendNegativeTestPayflowProVariation1" summary="Verify required fields validation for credit card on admin order creation" ticketId="MAGETWO-58934"> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S2</data> <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> <data name="customer/dataset" xsi:type="string">default</data> <data name="billingAddress/dataset" xsi:type="string">US_address_1_without_email</data> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateVaultOrderBackendTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateVaultOrderBackendTest.xml index 64a191040b8a451aede65fe73dc9785747509c4f..38666c36a2ba4e53641f45616060353ca5e5e22c 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateVaultOrderBackendTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateVaultOrderBackendTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Vault\Test\TestCase\CreateVaultOrderBackendTest" summary="Use saved for PayPal Payflow Pro credit card on admin order creation" ticketId="MAGETWO-47350"> <variation name="CreateVaultOrderBackendTestPayflowProVariation1" summary="Use saved for PayPal Payflow Pro credit card on admin order creation" ticketId="MAGETWO-47350"> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> <data name="customer/dataset" xsi:type="string">default</data> <data name="billingAddress/dataset" xsi:type="string">US_address_1_without_email</data> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.php index c8fb3e4f30f19834d1587cf1a1290aeeace7b958..8a10d08e0f6c3e6cdfddc7ec1a52d8796d54fca3 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.php +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.php @@ -31,6 +31,7 @@ class ExpressCheckoutFromProductPageTest extends Scenario const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; const TO_MAINTAIN = 'yes'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.xml index 4373523471cffc5e8e13b6bc01dffc9902516cd0..1d92fa149efbc336eb0910a451a1740f2eda6c14 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.xml @@ -27,7 +27,7 @@ </data> <data name="payment/method" xsi:type="string">paypal_express</data> <data name="configData" xsi:type="string">paypal_express, freeshipping</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.php index 7fc35ff1eb6fd83e929886bcdeac741de868fe68..6ecf356e27ff8c61a04329cb3211f0f6e1e9c05f 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.php +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.php @@ -31,6 +31,7 @@ class ExpressCheckoutFromShoppingCartTest extends Scenario const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; const TO_MAINTAIN = 'yes'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.xml index e4a4cd484a45a3b0ed0d8e015d791c207563b96a..38c876719bc3d82c772ff6f86cd507229ec5cf2b 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.xml @@ -28,7 +28,7 @@ <item name="grandTotal" xsi:type="string">145.98</item> </data> <data name="configData" xsi:type="string">payflowpro</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.php index b40adf986dbe9a7311fec484411bb8a7ed50810d..5d7056d32703dbe6b79c6b099ab9a11fa2b9d41f 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.php +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.php @@ -35,6 +35,7 @@ class ExpressCheckoutOnePageTest extends Scenario const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; const TO_MAINTAIN = 'yes'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.xml index df02c3293b50c5ed1bb2394bdeb6fc378f677874..e52ed631ae46f983dc8860e7bf628f95a5a6a7fb 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.xml @@ -26,7 +26,7 @@ </data> <data name="payment/method" xsi:type="string">paypal_express</data> <data name="configData" xsi:type="string">paypal_express</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> @@ -51,7 +51,7 @@ </data> <data name="payment/method" xsi:type="string">paypal_express</data> <data name="configData" xsi:type="string">payflowlink</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressCheckoutFromShoppingCartTest.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressCheckoutFromShoppingCartTest.php index 07f03b1c931cfc0c547f781451630fa828101294..66ca21d8d0f3eae424d9b3f926bf0003ff3dd9d6 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressCheckoutFromShoppingCartTest.php +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressCheckoutFromShoppingCartTest.php @@ -32,6 +32,7 @@ class InContextExpressCheckoutFromShoppingCartTest extends Scenario const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; const TO_MAINTAIN = 'yes'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressCheckoutFromShoppingCartTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressCheckoutFromShoppingCartTest.xml index 979a8c2f32db3fd9333adbfe6fd8b52263edf462..bbc566d1e31ec620746316d2e3ebcfe76c6883ae 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressCheckoutFromShoppingCartTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressCheckoutFromShoppingCartTest.xml @@ -10,7 +10,7 @@ <variation name="InContextExpressCheckoutFromShoppingCartTestVariation1" summary="In-Context Checkout with PayPal Express Checkout (API Credentials) from shopping cart " ticketId="MAGETWO-47213"> <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> <data name="configData" xsi:type="string">paypal_express, paypal_express_in_context</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Paypal\Test\Constraint\AssertExpressCancelledMessage" /> </variation> </testCase> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressOnePageCheckoutTest.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressOnePageCheckoutTest.php index ff06e6b10266ef4b723811bf143b648aa59853e9..b96f6a3e4a70a4ce320b0bf7b424675a0eee8fc4 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressOnePageCheckoutTest.php +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressOnePageCheckoutTest.php @@ -32,6 +32,7 @@ class InContextExpressOnePageCheckoutTest extends Scenario const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; const TO_MAINTAIN = 'yes'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressOnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressOnePageCheckoutTest.xml index cbdd9c3b6d6d31d13acac40ef5c8420b51054f85..5fa8e6e8b775dfb4e0bae646d431196823312f98 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressOnePageCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/InContextExpressOnePageCheckoutTest.xml @@ -18,7 +18,7 @@ </data> <data name="payment/method" xsi:type="string">paypal_express</data> <data name="configData" xsi:type="string">paypal_express_in_context, paypal_express, freeshipping</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Paypal\Test\Constraint\AssertExpressCancelledMessage" /> </variation> </testCase> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/NavigateMenuTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/NavigateMenuTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..379e90eb72c0d15c28b4de340f019ed21e9978c5 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/NavigateMenuTest.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Backend\Test\TestCase\NavigateMenuTest" summary="Navigate through admin menu" ticketId="MAGETWO-34874"> + <variation name="NavigateMenuTest50"> + <data name="tag" xsi:type="string">severity:S0</data> + <data name="menuItem" xsi:type="string">Reports > PayPal Settlement</data> + <data name="pageTitle" xsi:type="string">PayPal Settlement Reports</data> + <constraint name="Magento\Backend\Test\Constraint\AssertBackendPageIsAvailable"/> + </variation> + <variation name="NavigateMenuTest51"> + <data name="tag" xsi:type="string">severity:S0</data> + <data name="menuItem" xsi:type="string">Sales > Billing Agreements</data> + <data name="pageTitle" xsi:type="string">Billing Agreements</data> + <constraint name="Magento\Backend\Test\Constraint\AssertBackendPageIsAvailable"/> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml index bc3ee3cef1c68ba1668891cce3e6f2eb45a4d86d..c33abb1dbdd2263fded6dbbfb0f683848a3bdd3f 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml @@ -23,7 +23,7 @@ <data name="creditCard/dataset" xsi:type="string">visa_default</data> <data name="configData" xsi:type="string">payflowpro, payflowpro_use_vault</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Sales\Test\Constraint\AssertOrderSuccessCreateMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> <constraint name="Magento\Sales\Test\Constraint\AssertAuthorizationInCommentsHistory" /> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/UseVaultOnCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/UseVaultOnCheckoutTest.xml index bde3837d71fda02bad93ac1ced7c3c08835deafe..92b4be03b5937ffa318f9d3cd05f6e6d2290f6bc 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/UseVaultOnCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/UseVaultOnCheckoutTest.xml @@ -21,7 +21,7 @@ <data name="creditCardSave" xsi:type="string">Yes</data> <data name="configData" xsi:type="string">payflowpro, payflowpro_use_vault</data> <data name="status" xsi:type="string">Processing</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <data name="status" xsi:type="string">Processing</data> <data name="orderButtonsAvailable" xsi:type="string">Back, Cancel, Send Email, Hold, Invoice, Ship, Reorder, Edit</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/etc/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..e56386d5e0eacc346bfb5ddaf84319a1d1d16313 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/etc/di.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\Paypal\Test\Constraint\Sandbox\AssertTotalPaypalReview"> + <arguments> + <argument name="severity" xsi:type="string">S1</argument> + </arguments> + </type> + <type name="Magento\Paypal\Test\Constraint\AssertExpressCancelledMessage"> + <arguments> + <argument name="severity" xsi:type="string">S1</argument> + </arguments> + </type> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Ups/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Ups/Test/TestCase/OnePageCheckoutTest.xml index b27bc81d2866045de5c9e1d18fa4689a09a360d1..45076e90aab202b1cae7fbc5abcefbfc6c11e317 100644 --- a/dev/tests/functional/tests/app/Magento/Ups/Test/TestCase/OnePageCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Ups/Test/TestCase/OnePageCheckoutTest.xml @@ -20,7 +20,7 @@ <data name="cart/data/shipping_method" xsi:type="string">UPS Ground</data> <data name="payment/method" xsi:type="string">checkmo</data> <data name="configData" xsi:type="string">checkmo, ups, shipping_origin_US_CA</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage"/> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGrid"/> @@ -39,7 +39,7 @@ <data name="cart/data/shipping_method" xsi:type="string">UPS Worldwide Expedited</data> <data name="payment/method" xsi:type="string">checkmo</data> <data name="configData" xsi:type="string">checkmo, ups, shipping_origin_US_CA</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage"/> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGrid"/> diff --git a/dev/tests/functional/tests/app/Magento/Usps/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Usps/Test/TestCase/OnePageCheckoutTest.xml index 28c2b0f16239c735c927a8d3f7ef8eb0ebc1b01b..0bd219bab3bfff2103ea9f7a1ff2934ca8e1ad59 100644 --- a/dev/tests/functional/tests/app/Magento/Usps/Test/TestCase/OnePageCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Usps/Test/TestCase/OnePageCheckoutTest.xml @@ -20,7 +20,7 @@ <data name="cart/data/shipping_method" xsi:type="string">Priority Mail 1-Day</data> <data name="payment/method" xsi:type="string">checkmo</data> <data name="configData" xsi:type="string">checkmo, usps, shipping_origin_US_CA</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage"/> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGrid"/> @@ -37,7 +37,7 @@ <data name="cart/data/shipping_method" xsi:type="string">Priority Mail Express International Flat Rate Envelope</data> <data name="payment/method" xsi:type="string">checkmo</data> <data name="configData" xsi:type="string">checkmo, usps, shipping_origin_US_CA</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage"/> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGrid"/> diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/CreateVaultOrderBackendTest.php b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/CreateVaultOrderBackendTest.php index 3c306280215ea1a2ee460db6f7838fd7c33caf7c..a5194b3915191e7c5ef893bcb5958d610544ddf7 100644 --- a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/CreateVaultOrderBackendTest.php +++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/CreateVaultOrderBackendTest.php @@ -38,6 +38,7 @@ class CreateVaultOrderBackendTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = 'acceptance_test, extended_acceptance_test, 3rd_party_test'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.php b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.php index 17db35df1b44e6d2be519426ba962f6696fee23d..e6462e4697aa612c1239b92b3c7b7e847bd252ba 100644 --- a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.php +++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.php @@ -32,6 +32,7 @@ class DeleteSavedCreditCardTest extends Injectable /* tags */ const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S1'; /* end tags */ /** 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 ae303b695277c53272efedc40231bf305b66fea5..ac69bfb9f47e4550e6ab4592cccbdf56cf682da3 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 @@ -52,7 +52,7 @@ </data> <data name="creditCardSave" xsi:type="string">Yes</data> <data name="configData" xsi:type="string">braintree, payflowpro, braintree_use_vault, payflowpro_use_vault</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/ReorderUsingVaultTest.php b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/ReorderUsingVaultTest.php index c3b82af6949c4a0ea114324abae90aa7ccab3a24..e426662d30e5447599f0b2f4bc47b67902aeb7c9 100644 --- a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/ReorderUsingVaultTest.php +++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/ReorderUsingVaultTest.php @@ -36,6 +36,8 @@ class ReorderUsingVaultTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = 'extended_acceptance_test, 3rd_party_test'; + const SEVERITY = 'S1'; + /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/UseVaultOnCheckoutTest.php b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/UseVaultOnCheckoutTest.php index 902ccc62af7f57c23db399bc22d5d3530b0a7515..fb8b3575ee72e463254038446ce55561123e3103 100644 --- a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/UseVaultOnCheckoutTest.php +++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/UseVaultOnCheckoutTest.php @@ -39,6 +39,7 @@ class UseVaultOnCheckoutTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Vault/Test/etc/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..aba54057312ea3491655b5ea6e75c9fef4dfc2ae --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Vault/Test/etc/di.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\Vault\Test\Constraint\AssertCreditCardNotPresentOnCheckout"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Vault\Test\Constraint\AssertStoredPaymentDeletedMessage"> + <arguments> + <argument name="severity" xsi:type="string">S1</argument> + </arguments> + </type> +</config> diff --git a/dev/tests/functional/testsuites/Magento/Mtf/TestSuite/InjectableTests/basic.xml b/dev/tests/functional/testsuites/Magento/Mtf/TestSuite/InjectableTests/basic.xml index 4b4ab839d3463cbef4c766161e41874d0d65e446..6836259eb671ac908ad017138bde36a86e764766 100644 --- a/dev/tests/functional/testsuites/Magento/Mtf/TestSuite/InjectableTests/basic.xml +++ b/dev/tests/functional/testsuites/Magento/Mtf/TestSuite/InjectableTests/basic.xml @@ -7,11 +7,6 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../vendor/magento/mtf/Magento/Mtf/TestRunner/etc/testRunner.xsd"> - <rule scope="testcase"> - <deny> - <tag group="test_type" value="3rd_party_test_deprecated" /> - </deny> - </rule> <rule scope="variation"> <deny> <tag group="test_type" value="3rd_party_test" /> diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Set/SaveTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Set/SaveTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4738e1886be3e6d9ab64f65cd7f241b63453a741 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Set/SaveTest.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Controller\Adminhtml\Product\Set; + +use Magento\Eav\Api\AttributeSetRepositoryInterface; +use Magento\Eav\Api\Data\AttributeSetInterface; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\TestFramework\Helper\Bootstrap; + +class SaveTest extends \Magento\TestFramework\TestCase\AbstractBackendController +{ + /** + * @magentoDataFixture Magento/Catalog/_files/attribute_set_with_renamed_group.php + */ + public function testAlreadyExistsExceptionProcessingWhenGroupCodeIsDuplicated() + { + $attributeSet = $this->getAttributeSetByName('attribute_set_test'); + $this->assertNotEmpty($attributeSet, 'Attribute set with name "attribute_set_test" is missed'); + + $this->getRequest()->setPostValue('data', json_encode([ + 'attribute_set_name' => 'attribute_set_test', + 'groups' => [ + ['ynode-418', 'attribute-group-name', 1], + ], + 'attributes' => [ + ['9999', 'ynode-418', 1, null] + ], + 'not_attributes' => [], + 'removeGroups' => [], + ])); + $this->dispatch('backend/catalog/product_set/save/id/' . $attributeSet->getAttributeSetId()); + + $jsonResponse = json_decode($this->getResponse()->getBody()); + $this->assertNotNull($jsonResponse); + $this->assertEquals(1, $jsonResponse->error); + $this->assertContains( + 'Attribute group with same code already exist. Please rename "attribute-group-name" group', + $jsonResponse->message + ); + } + + /** + * @param string $attributeSetName + * @return AttributeSetInterface|null + */ + protected function getAttributeSetByName($attributeSetName) + { + $objectManager = Bootstrap::getObjectManager(); + + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $objectManager->get(SearchCriteriaBuilder::class); + $searchCriteriaBuilder->addFilter('attribute_set_name', $attributeSetName); + + /** @var AttributeSetRepositoryInterface $attributeSetRepository */ + $attributeSetRepository = $objectManager->get(AttributeSetRepositoryInterface::class); + $result = $attributeSetRepository->getList($searchCriteriaBuilder->create()); + + $items = $result->getItems(); + return $result->getTotalCount() ? array_pop($items) : null; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_renamed_group.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_renamed_group.php new file mode 100644 index 0000000000000000000000000000000000000000..d73baa9e70e023d55e0a3306a03f8b7a56666b86 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_renamed_group.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +use Magento\Catalog\Api\AttributeSetRepositoryInterface; +use Magento\Eav\Api\AttributeGroupRepositoryInterface; +use Magento\Eav\Api\Data\AttributeGroupInterface; +use Magento\Eav\Api\Data\AttributeGroupInterfaceFactory; +use Magento\Eav\Api\Data\AttributeSetInterface; +use Magento\Eav\Api\Data\AttributeSetInterfaceFactory; +use Magento\Eav\Model\Entity\Type; +use Magento\Framework\Api\DataObjectHelper; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +$attributeSetFactory = $objectManager->get(AttributeSetInterfaceFactory::class); +$attributeGroupFactory = $objectManager->get(AttributeGroupInterfaceFactory::class); +/** @var DataObjectHelper $dataObjectHelper */ +$dataObjectHelper = $objectManager->get(DataObjectHelper::class); +/** @var AttributeGroupRepositoryInterface $attributeGroupRepository */ +$attributeGroupRepository = $objectManager->get(AttributeGroupRepositoryInterface::class); +/** @var AttributeSetRepositoryInterface $attributeSetRepository */ +$attributeSetRepository = $objectManager->get(AttributeSetRepositoryInterface::class); + +/** @var AttributeSetInterface $attributeSet */ +$attributeSet = $attributeSetFactory->create(); +$entityTypeId = $objectManager->create(Type::class)->loadByCode('catalog_product')->getId(); +$dataObjectHelper->populateWithArray( + $attributeSet, + [ + 'attribute_set_name' => 'attribute_set_test', + 'entity_type_id' => $entityTypeId, + ], + AttributeSetInterface::class +); +$attributeSetRepository->save($attributeSet); + +/** @var AttributeGroupInterface $attributeGroup */ +$attributeGroup = $attributeGroupFactory->create(); +$dataObjectHelper->populateWithArray( + $attributeGroup, + [ + 'attribute_set_id' => $attributeSet->getAttributeSetId(), + 'attribute_group_name' => 'attribute-group-name', + 'default_id' => 1, + ], + AttributeGroupInterface::class +); +$attributeGroupRepository->save($attributeGroup); + +// during renaming group code is not changed +$attributeGroup->setAttributeGroupName('attribute-group-renamed'); +$attributeGroupRepository->save($attributeGroup); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/multiselect_attribute.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/multiselect_attribute.php index 2c9d6ca91e9f9cd2487067389fc119b24ca4a3bc..963de3e46fea69c821902b8d4266681adc0d5ea8 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/multiselect_attribute.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/multiselect_attribute.php @@ -40,7 +40,7 @@ $attribute->setData( 'option_1' => ['Option 1'], 'option_2' => ['Option 2'], 'option_3' => ['Option 3'], - 'option_4' => ['Option 4 "!@#$%^&*'], + 'option_4' => ['Option 4 "!@#$%^&*'] ], 'order' => [ 'option_1' => 1, diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/multiselect_attribute_with_incorrect_values.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/multiselect_attribute_with_incorrect_values.php new file mode 100644 index 0000000000000000000000000000000000000000..1ab2f9ef65bffca50886f8c7ef4764c550da0aa5 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/multiselect_attribute_with_incorrect_values.php @@ -0,0 +1,55 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/* Create attribute */ +/** @var $installer \Magento\Catalog\Setup\CategorySetup */ +$installer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Setup\CategorySetup::class +); +/** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ +$attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class +); +$attribute->setData( + [ + 'attribute_code' => 'multiselect_attribute', + 'entity_type_id' => $installer->getEntityTypeId('catalog_product'), + 'is_global' => 1, + 'is_user_defined' => 1, + 'frontend_input' => 'multiselect', + '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' => ['Multiselect Attribute'], + 'backend_type' => 'varchar', + 'backend_model' => \Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend::class, + 'option' => [ + 'value' => [ + 'option_1' => ['Opt|,=ion 1'], + 'option_2' => ['Opt||,ion 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', 'General', $attribute->getId()); diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php index 9b06764ce264cfe9aaa6be03a6e61f2f01210631..dc9e440b045f86ad2e85de45124ac01881d3892c 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php @@ -206,4 +206,55 @@ class ProductTest extends \PHPUnit_Framework_TestCase $data = $model->setWriter($exportAdapter)->export(); $this->assertEmpty($data); } + + /** + * Verify if fields wrapping works correct when "Fields Enclosure" option enabled + * + * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_data.php + */ + public function testExportWithFieldsEnclosure() + { + $this->model->setParameters([ + \Magento\ImportExport\Model\Export::FIELDS_ENCLOSURE => 1 + ]); + + $this->model->setWriter( + $this->objectManager->create( + \Magento\ImportExport\Model\Export\Adapter\Csv::class + ) + ); + $exportData = $this->model->export(); + + $this->assertContains('""Option 2""', $exportData); + $this->assertContains('""Option 3""', $exportData); + $this->assertContains('""Option 4 """"!@#$%^&*""', $exportData); + $this->assertContains('text_attribute=""!@#$%^&*()_+1234567890-=|\:;""""\'<,>.?/', $exportData); + } + + /** + * Verify that "category ids" filter correctly applies to export result + * + * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_with_categories.php + */ + public function testCategoryIdsFilter() + { + $this->model->setWriter( + $this->objectManager->create( + \Magento\ImportExport\Model\Export\Adapter\Csv::class + ) + ); + + $this->model->setParameters([ + \Magento\ImportExport\Model\Export::FILTER_ELEMENT_GROUP => [ + 'category_ids' => '2,13' + ] + ]); + + $exportData = $this->model->export(); + + $this->assertContains('Simple Product', $exportData); + $this->assertContains('Simple Product Three', $exportData); + $this->assertNotContains('Simple Product Two', $exportData); + $this->assertNotContains('Simple Product Not Visible On Storefront', $exportData); + } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index a5c1f07c164156a0941b0f8da05c43bdff644b5e..9ab7db147d811d370a4c2609d5baf5ea35225680 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -1380,4 +1380,55 @@ class ProductTest extends \Magento\TestFramework\Indexer\TestCase array_values($actualProductSkus) ); } + + /** + * @magentoDataFixture Magento/Catalog/_files/multiselect_attribute_with_incorrect_values.php + * @magentoDataFixture Magento/Catalog/_files/product_text_attribute.php + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + */ + public function testProductWithWrappedAdditionalAttributes() + { + $filesystem = $this->objectManager->create(\Magento\Framework\Filesystem::class); + $directory = $filesystem->getDirectoryWrite(DirectoryList::ROOT); + $source = $this->objectManager->create( + \Magento\ImportExport\Model\Import\Source\Csv::class, + [ + 'file' => __DIR__ . '/_files/products_to_import_with_additional_attributes.csv', + 'directory' => $directory + ] + ); + $errors = $this->_model->setParameters( + [ + 'behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, + 'entity' => 'catalog_product', + \Magento\ImportExport\Model\Import::FIELDS_ENCLOSURE => 1 + ] + )->setSource( + $source + )->validateData(); + + $this->assertTrue($errors->getErrorsCount() == 0); + + $this->_model->importData(); + + /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ + $productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Api\ProductRepositoryInterface::class + ); + + /** @var \Magento\Eav\Api\AttributeOptionManagementInterface $multiselectOptions */ + $multiselectOptions = $this->objectManager->get(\Magento\Eav\Api\AttributeOptionManagementInterface::class) + ->getItems(\Magento\Catalog\Model\Product::ENTITY, 'multiselect_attribute'); + + $product1 = $productRepository->get('simple1'); + $this->assertEquals('\'", =|', $product1->getData('text_attribute')); + $this->assertEquals(implode(',', [$multiselectOptions[3]->getValue(), $multiselectOptions[2]->getValue()]), + $product1->getData('multiselect_attribute')); + + $product2 = $productRepository->get('simple2'); + $this->assertEquals('', $product2->getData('text_attribute')); + $this->assertEquals(implode(',', [$multiselectOptions[1]->getValue(), $multiselectOptions[2]->getValue()]), + $product2->getData('multiselect_attribute')); + } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_additional_attributes.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_additional_attributes.csv new file mode 100644 index 0000000000000000000000000000000000000000..eb882be4c6bb1dcb804cd284e1ce376c31feec37 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_additional_attributes.csv @@ -0,0 +1,3 @@ +sku,product_type,name,price,attribute_set_code,categories,additional_attributes +simple1,simple,"simple 1",25,Default,"Default Category/Category 1","text_attribute=""'"""", =|"",multiselect_attribute=""Option 3 """"!@#$%^&*, """"|""""""|""Opt||,ion 2""" +simple2,simple,"simple 2",34,Default,"Default Category/Category 1","multiselect_attribute=""Opt|,=ion 1""|""Opt||,ion 2"",text_attribute=""""" diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_categories.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_categories.php new file mode 100644 index 0000000000000000000000000000000000000000..e65ff00bcffcabd1e2fdeae3810876178e0d06aa --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_categories.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +\Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize(); + +require dirname(dirname(__DIR__)) . '/Catalog/_files/categories.php'; diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_shipping_method_and_items_categories.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_shipping_method_and_items_categories.php index 7fb35a4412bf8bbbda969b646a23eee84aac61ac..ec230f3c5126185e21d27226c65f6e09e7f125e5 100644 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_shipping_method_and_items_categories.php +++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_shipping_method_and_items_categories.php @@ -56,7 +56,7 @@ $product->setTypeId( )->setId( 444 )->setAttributeSetId( - 5 + 4 )->setStoreId( 1 )->setWebsiteIds( diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Block/Adminhtml/Export/Edit/FormTest.php b/dev/tests/integration/testsuite/Magento/ImportExport/Block/Adminhtml/Export/Edit/FormTest.php index 52fbe5ed7b6afbbd85f65aa864c453e46810facb..a463a426dd647cde6d352be51f63bd82a59db5d1 100644 --- a/dev/tests/integration/testsuite/Magento/ImportExport/Block/Adminhtml/Export/Edit/FormTest.php +++ b/dev/tests/integration/testsuite/Magento/ImportExport/Block/Adminhtml/Export/Edit/FormTest.php @@ -30,7 +30,11 @@ class FormTest extends \PHPUnit_Framework_TestCase * * @var array */ - protected $_expectedFields = ['base_fieldset' => ['entity' => 'entity', 'file_format' => 'file_format']]; + protected $_expectedFields = ['base_fieldset' => [ + 'entity' => 'entity', + 'file_format' => 'file_format', + 'fields_enclosure' => 'fields_enclosure' + ]]; protected function setUp() { diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/ExportTest.php b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/ExportTest.php index 9decf617d50ae1ca0b8c895b3d45e5c255d846cd..de9379d1494d3925590f228ea52c69934fd9bd8b 100644 --- a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/ExportTest.php +++ b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/ExportTest.php @@ -84,6 +84,6 @@ class ExportTest extends \Magento\TestFramework\TestCase\AbstractBackendControll $body = $this->getResponse()->getBody(); $this->assertSelectCount('fieldset#base_fieldset', 1, $body); - $this->assertSelectCount('fieldset#base_fieldset div.field', 2, $body); + $this->assertSelectCount('fieldset#base_fieldset div.field', 3, $body); } } diff --git a/dev/tests/static/get_github_changes.php b/dev/tests/static/get_github_changes.php index c142aae18d8ecd5a4ab3fa895e32e5510b71683b..f332208cd17d0861dd1b28bd7096a0b3fe0066a5 100644 --- a/dev/tests/static/get_github_changes.php +++ b/dev/tests/static/get_github_changes.php @@ -12,9 +12,9 @@ // @codingStandardsIgnoreFile define( -'USAGE', -<<<USAGE - php -f get_github_changes.php -- + 'USAGE', + <<<USAGE + php -f get_github_changes.php -- --output-file="<output_file>" --base-path="<base_path>" --repo="<main_repo>" @@ -36,6 +36,8 @@ $fileExtensions = explode(',', isset($options['file-extensions']) ? $options['fi $mainline = 'mainline_' . (string)rand(0, 9999); $repo = getRepo($options, $mainline); +$branches = $repo->getBranches('--remotes'); +generateBranchesList($options['output-file'], $branches, $options['branch']); $changes = retrieveChangesAcrossForks($mainline, $repo, $options['branch']); $changedFiles = getChangedFiles($changes, $fileExtensions); generateChangedFilesList($options['output-file'], $changedFiles); @@ -57,6 +59,25 @@ function generateChangedFilesList($outputFile, $changedFiles) fclose($changedFilesList); } +/** + * Generates a file containing origin branches + * + * @param string $outputFile + * @param array $branches + * @param string $branchName + * @return void + */ +function generateBranchesList($outputFile, $branches, $branchName) +{ + $branchOutputFile = str_replace('changed_files', 'branches', $outputFile); + $branchesList = fopen($branchOutputFile, 'w'); + fwrite($branchesList, $branchName . PHP_EOL); + foreach ($branches as $branch) { + fwrite($branchesList, substr(strrchr($branch, '/'), 1) . PHP_EOL); + } + fclose($branchesList); +} + /** * Gets list of changed files * @@ -84,7 +105,7 @@ function getChangedFiles(array $changes, array $fileExtensions) * * @param array $options * @param string $mainline - * @return array + * @return GitRepo * @throws Exception */ function getRepo($options, $mainline) @@ -203,6 +224,19 @@ class GitRepo $this->call(sprintf('fetch %s', $remoteAlias)); } + /** + * Returns branches + * + * @param string $source + * @return array|mixed + */ + public function getBranches($source = '--all') + { + $result = $this->call(sprintf('branch ' . $source)); + + return is_array($result) ? $result : []; + } + /** * Returns files changes between branch and HEAD * diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/exception_hierarchy.txt b/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/exception_hierarchy.txt index 9ae1f7fc1452d3156aa7308ee3f81d194e99bbce..a50845d3884adf110ff8c36831e6ef8ac63670ca 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/exception_hierarchy.txt +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/exception_hierarchy.txt @@ -6,3 +6,4 @@ \Magento\Framework\DB\Adapter\ConnectionException \Magento\Framework\DB\Adapter\DeadlockException \Magento\Framework\DB\Adapter\LockWaitException +\Magento\Framework\DB\Adapter\DuplicateException diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php index 87bd329ef3b5611475c6ee9486cdc9f27c4ea5fe..2f3d312fb41ffba1287bafd324a64ac751316d5c 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php @@ -15,38 +15,49 @@ class ModuleDBChangeTest extends \PHPUnit_Framework_TestCase /** * @var string */ - protected static $changedFilesPattern = __DIR__ . '/../_files/changed_files*'; + private static $branchesFilesPattern = __DIR__ . '/../_files/branches*'; /** * @var string */ - protected static $changedFileList = ''; + private static $changedFilesPattern = __DIR__ . '/../_files/changed_files*'; /** - * @var string Path for Magento's composer.json + * @var string */ - protected static $composerFilePath = BP . '/composer.json'; + private static $changedFileList = ''; /** - * @var bool Is tests executes on develop branch + * @var bool */ - protected static $isOnDevVersion = false; + private static $actualBranch = false; /** * Set changed files paths and list for all projects */ public static function setUpBeforeClass() { - foreach (glob(self::$changedFilesPattern) as $changedFile) { - self::$changedFileList .= file_get_contents($changedFile) . PHP_EOL; - } + foreach (glob(self::$branchesFilesPattern) as $branchesFile) { + //get the current branchname from the first line + $branchName = trim(file($branchesFile)[0]); + if ($branchName === 'develop') { + self::$actualBranch = true; + } else { + //get current minor branch name + preg_match('|^(\d+\.\d+)|', $branchName, $minorBranch); + $branchName = $minorBranch[0]; + + //get all version branches + preg_match_all('|^(\d+\.\d+)|m', file_get_contents($branchesFile), $matches); - if (file_exists(self::$composerFilePath)) { - $jsonData = json_decode(file_get_contents(self::$composerFilePath)); - if (substr((string) $jsonData->version, -4) == '-dev') { - self::$isOnDevVersion = true; + //check is this a latest release branch + self::$actualBranch = ($branchName == max($matches[0])); } } + + foreach (glob(self::$changedFilesPattern) as $changedFile) { + self::$changedFileList .= file_get_contents($changedFile) . PHP_EOL; + } } /** @@ -54,15 +65,14 @@ class ModuleDBChangeTest extends \PHPUnit_Framework_TestCase */ public function testModuleXmlFiles() { - if (self::$isOnDevVersion) { - $this->markTestSkipped('This test isn\'t applicable to the developer version of Magento'); + if (!self::$actualBranch) { + preg_match_all('|etc/module\.xml$|mi', self::$changedFileList, $matches); + $this->assertEmpty( + reset($matches), + 'module.xml changes for patch releases in non-actual branches are not allowed:' . PHP_EOL . + implode(PHP_EOL, array_values(reset($matches))) + ); } - preg_match_all('|etc/module\.xml$|mi', self::$changedFileList, $matches); - $this->assertEmpty( - reset($matches), - 'module.xml changes for patch releases in non-actual branches are not allowed:' . PHP_EOL . - implode(PHP_EOL, array_values(reset($matches))) - ); } /** @@ -70,14 +80,13 @@ class ModuleDBChangeTest extends \PHPUnit_Framework_TestCase */ public function testModuleSetupFiles() { - if (self::$isOnDevVersion) { - $this->markTestSkipped('This test isn\'t applicable to the developer version of Magento'); + if (!self::$actualBranch) { + preg_match_all('|app/code/Magento/[^/]+/Setup/[^/]+$|mi', self::$changedFileList, $matches); + $this->assertEmpty( + reset($matches), + 'Code with changes for DB schema or data in non-actual branches are not allowed:' . PHP_EOL . + implode(PHP_EOL, array_values(reset($matches))) + ); } - preg_match_all('|app/code/Magento/[^/]+/Setup/[^/]+$|mi', self::$changedFileList, $matches); - $this->assertEmpty( - reset($matches), - 'Code with changes for DB schema or data in non-actual branches are not allowed:' . PHP_EOL . - implode(PHP_EOL, array_values(reset($matches))) - ); } } diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/blacklist.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/blacklist.php index f055f0a732c664dd8ed109d7ec52b178c537a4d0..d120a4543b9ddced597d330ab489de15c80cdb86 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/blacklist.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/blacklist.php @@ -4,5 +4,6 @@ * See COPYING.txt for license details. */ return [ - '/Test\/Unit/' + '/Test\/Unit/', + '/lib\/internal\/Magento\/Framework\/DB\/Adapter\/Pdo\/Mysql\.php/', ]; diff --git a/lib/internal/Magento/Framework/App/Cache/Type/Dummy.php b/lib/internal/Magento/Framework/App/Cache/Type/Dummy.php new file mode 100644 index 0000000000000000000000000000000000000000..ea6a3c3e92e7e615740990170d218608aff99836 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Cache/Type/Dummy.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Cache\Type; + +use Magento\Framework\App\CacheInterface; + +/** + * Dummy cache adapter + * + * for cases when need to disable interaction with cache + * but no specific cache type is used + */ +class Dummy implements CacheInterface +{ + /** + * Required by CacheInterface + * + * @return null + */ + public function getFrontend() + { + return null; + } + + /** + * Pretend to load data from cache by id + * + * {@inheritdoc} + */ + public function load($identifier) + { + return null; + } + + /** + * Pretend to save data + * + * {@inheritdoc} + */ + public function save($data, $identifier, $tags = [], $lifeTime = null) + { + return false; + } + + /** + * Pretend to remove cached data by identifier + * + * {@inheritdoc} + */ + public function remove($identifier) + { + return true; + } + + /** + * Pretend to clean cached data by specific tag + * + * {@inheritdoc} + */ + public function clean($tags = []) + { + return true; + } +} diff --git a/lib/internal/Magento/Framework/DB/Adapter/DuplicateException.php b/lib/internal/Magento/Framework/DB/Adapter/DuplicateException.php new file mode 100644 index 0000000000000000000000000000000000000000..06c4dfcc30ab26572b0faae1d90d1939989455ba --- /dev/null +++ b/lib/internal/Magento/Framework/DB/Adapter/DuplicateException.php @@ -0,0 +1,13 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\DB\Adapter; + +/** + * Database duplicate exception + */ +class DuplicateException extends \Zend_Db_Adapter_Exception +{ +} diff --git a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php index 6399824590a696980b641abcd3d0fc5b4e09cf42..cfbeb4f54c9e29d2f7b320b57c51ae7a7b31a676 100644 --- a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php +++ b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php @@ -14,6 +14,7 @@ use Magento\Framework\Cache\FrontendInterface; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Adapter\ConnectionException; use Magento\Framework\DB\Adapter\DeadlockException; +use Magento\Framework\DB\Adapter\DuplicateException; use Magento\Framework\DB\Adapter\LockWaitException; use Magento\Framework\DB\Ddl\Table; use Magento\Framework\DB\ExpressionConverter; @@ -232,6 +233,8 @@ class Mysql extends \Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface 1205 => LockWaitException::class, // SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock 1213 => DeadlockException::class, + // SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry + 1062 => DuplicateException::class, ]; try { parent::__construct($config); @@ -465,7 +468,7 @@ class Mysql extends \Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface * @param mixed $bind An array of data or data itself to bind to the placeholders. * @return \Zend_Db_Statement_Pdo|void * @throws \Zend_Db_Adapter_Exception To re-throw \PDOException. - * @throws LocalizedException In case multiple queries are attempted at once, to protect from SQL injection + * @throws \Zend_Db_Statement_Exception * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function _query($sql, $bind = []) diff --git a/lib/internal/Magento/Framework/EntityManager/Operation/Create.php b/lib/internal/Magento/Framework/EntityManager/Operation/Create.php index 7e3dfb2e753caa4ebd8efc72c159b0b3a3d521d4..552fe7bca86f58fb722fab1b08294b4ee41d3734 100644 --- a/lib/internal/Magento/Framework/EntityManager/Operation/Create.php +++ b/lib/internal/Magento/Framework/EntityManager/Operation/Create.php @@ -5,7 +5,7 @@ */ namespace Magento\Framework\EntityManager\Operation; -use Magento\Framework\EntityManager\Operation\CreateInterface; +use Magento\Framework\DB\Adapter\DuplicateException; use Magento\Framework\EntityManager\Operation\Create\CreateMain; use Magento\Framework\EntityManager\Operation\Create\CreateAttributes; use Magento\Framework\EntityManager\Operation\Create\CreateExtensions; @@ -13,6 +13,8 @@ use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\EntityManager\EventManager; use Magento\Framework\EntityManager\TypeResolver; use Magento\Framework\App\ResourceConnection; +use Magento\Framework\Exception\AlreadyExistsException; +use Magento\Framework\Phrase; /** * Class Create @@ -86,6 +88,7 @@ class Create implements CreateInterface * @param array $arguments * @return object * @throws \Exception + * @throws AlreadyExistsException */ public function execute($entity, $arguments = []) { @@ -114,6 +117,9 @@ class Create implements CreateInterface ] ); $connection->commit(); + } catch (DuplicateException $e) { + $connection->rollBack(); + throw new AlreadyExistsException(new Phrase('Unique constraint violation found'), $e); } catch (\Exception $e) { $connection->rollBack(); throw $e; diff --git a/lib/internal/Magento/Framework/EntityManager/Operation/Update.php b/lib/internal/Magento/Framework/EntityManager/Operation/Update.php index 22abb464f8cd9ad96713899ca95fc0a3dc87e782..dbc8dc63873498888a40396795f9d6a0b9edca19 100644 --- a/lib/internal/Magento/Framework/EntityManager/Operation/Update.php +++ b/lib/internal/Magento/Framework/EntityManager/Operation/Update.php @@ -5,7 +5,7 @@ */ namespace Magento\Framework\EntityManager\Operation; -use Magento\Framework\EntityManager\Operation\UpdateInterface; +use Magento\Framework\DB\Adapter\DuplicateException; use Magento\Framework\EntityManager\Operation\Update\UpdateMain; use Magento\Framework\EntityManager\Operation\Update\UpdateAttributes; use Magento\Framework\EntityManager\Operation\Update\UpdateExtensions; @@ -13,6 +13,8 @@ use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\EntityManager\EventManager; use Magento\Framework\EntityManager\TypeResolver; use Magento\Framework\App\ResourceConnection; +use Magento\Framework\Exception\AlreadyExistsException; +use Magento\Framework\Phrase; /** * Class Update @@ -114,6 +116,9 @@ class Update implements UpdateInterface ] ); $connection->commit(); + } catch (DuplicateException $e) { + $connection->rollBack(); + throw new AlreadyExistsException(new Phrase('Unique constraint violation found'), $e); } catch (\Exception $e) { $connection->rollBack(); throw $e; diff --git a/lib/internal/Magento/Framework/EntityManager/Test/Unit/Operation/CreateTest.php b/lib/internal/Magento/Framework/EntityManager/Test/Unit/Operation/CreateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e45e8ffac1934859b16fd040505865d2f078eed3 --- /dev/null +++ b/lib/internal/Magento/Framework/EntityManager/Test/Unit/Operation/CreateTest.php @@ -0,0 +1,78 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\EntityManager\Test\Unit\Operation; + +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DataObject; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\DB\Adapter\DuplicateException; +use Magento\Framework\EntityManager\EntityMetadataInterface; +use Magento\Framework\EntityManager\MetadataPool; +use Magento\Framework\EntityManager\Operation\Create; +use Magento\Framework\EntityManager\Operation\Create\CreateMain; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class CreateTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var MetadataPool|\PHPUnit_Framework_MockObject_MockObject + */ + private $metadataPool; + + /** + * @var ResourceConnection|\PHPUnit_Framework_MockObject_MockObject + */ + private $resourceConnection; + + /** + * @var CreateMain|\PHPUnit_Framework_MockObject_MockObject + */ + private $createMain; + + /** + * @var Create + */ + private $create; + + public function setUp() + { + $this->metadataPool = $this->getMockBuilder(MetadataPool::class) + ->disableOriginalConstructor() + ->getMock(); + $this->resourceConnection = $this->getMockBuilder(ResourceConnection::class) + ->disableOriginalConstructor() + ->getMock(); + $this->createMain = $this->getMockBuilder(CreateMain::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->create = (new ObjectManager($this))->getObject(Create::class, [ + 'metadataPool' => $this->metadataPool, + 'resourceConnection' => $this->resourceConnection, + 'createMain' => $this->createMain, + ]); + } + + /** + * @expectedException \Magento\Framework\Exception\AlreadyExistsException + */ + public function testDuplicateExceptionProcessingOnExecute() + { + $metadata = $this->getMock(EntityMetadataInterface::class); + $this->metadataPool->expects($this->any())->method('getMetadata')->willReturn($metadata); + + $connection = $this->getMock(AdapterInterface::class); + $connection->expects($this->once())->method('rollback'); + $this->resourceConnection->expects($this->any())->method('getConnectionByName')->willReturn($connection); + + $this->createMain->expects($this->once())->method('execute')->willThrowException(new DuplicateException()); + + $entity = $this->getMockBuilder(DataObject::class) + ->disableOriginalConstructor() + ->getMock(); + $this->create->execute($entity); + } +} diff --git a/lib/internal/Magento/Framework/EntityManager/Test/Unit/Operation/UpdateTest.php b/lib/internal/Magento/Framework/EntityManager/Test/Unit/Operation/UpdateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2ec78c2560a28b3d0cd2043b8fa09fe653e49be8 --- /dev/null +++ b/lib/internal/Magento/Framework/EntityManager/Test/Unit/Operation/UpdateTest.php @@ -0,0 +1,78 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\EntityManager\Test\Unit\Operation; + +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DataObject; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\DB\Adapter\DuplicateException; +use Magento\Framework\EntityManager\EntityMetadataInterface; +use Magento\Framework\EntityManager\MetadataPool; +use Magento\Framework\EntityManager\Operation\Update; +use Magento\Framework\EntityManager\Operation\Update\UpdateMain; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class UpdateTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var MetadataPool|\PHPUnit_Framework_MockObject_MockObject + */ + private $metadataPool; + + /** + * @var ResourceConnection|\PHPUnit_Framework_MockObject_MockObject + */ + private $resourceConnection; + + /** + * @var UpdateMain|\PHPUnit_Framework_MockObject_MockObject + */ + private $updateMain; + + /** + * @var Update + */ + private $update; + + public function setUp() + { + $this->metadataPool = $this->getMockBuilder(MetadataPool::class) + ->disableOriginalConstructor() + ->getMock(); + $this->resourceConnection = $this->getMockBuilder(ResourceConnection::class) + ->disableOriginalConstructor() + ->getMock(); + $this->updateMain = $this->getMockBuilder(UpdateMain::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->update = (new ObjectManager($this))->getObject(Update::class, [ + 'metadataPool' => $this->metadataPool, + 'resourceConnection' => $this->resourceConnection, + 'updateMain' => $this->updateMain, + ]); + } + + /** + * @expectedException \Magento\Framework\Exception\AlreadyExistsException + */ + public function testDuplicateExceptionProcessingOnExecute() + { + $metadata = $this->getMock(EntityMetadataInterface::class); + $this->metadataPool->expects($this->any())->method('getMetadata')->willReturn($metadata); + + $connection = $this->getMock(AdapterInterface::class); + $connection->expects($this->once())->method('rollback'); + $this->resourceConnection->expects($this->any())->method('getConnectionByName')->willReturn($connection); + + $this->updateMain->expects($this->once())->method('execute')->willThrowException(new DuplicateException()); + + $entity = $this->getMockBuilder(DataObject::class) + ->disableOriginalConstructor() + ->getMock(); + $this->update->execute($entity); + } +} diff --git a/lib/internal/Magento/Framework/Exception/AlreadyExistsException.php b/lib/internal/Magento/Framework/Exception/AlreadyExistsException.php index dd39ec8c709a75fa4c4a8721dd8fdbfed4499c2f..18afdacf53de2676525f70fd76e5b94b3671dddb 100644 --- a/lib/internal/Magento/Framework/Exception/AlreadyExistsException.php +++ b/lib/internal/Magento/Framework/Exception/AlreadyExistsException.php @@ -3,9 +3,24 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Framework\Exception; +use Magento\Framework\Phrase; + +/** + * Class AlreadyExistsException + */ class AlreadyExistsException extends LocalizedException { + /** + * @param Phrase $phrase + * @param \Exception $cause + */ + public function __construct(Phrase $phrase = null, \Exception $cause = null) + { + if ($phrase === null) { + $phrase = new Phrase('Unique constraint violation found'); + } + parent::__construct($phrase, $cause); + } } diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php index 7febcb450f9720d9999f19704808df90ca69deea..4cd88e356e9cad79a6f0209bb2bab685ffe5f73c 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php @@ -10,6 +10,8 @@ use Magento\Framework\App\ResourceConnection; use Magento\Framework\Exception\AlreadyExistsException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Model\ResourceModel\AbstractResource; +use Magento\Framework\DB\Adapter\DuplicateException; +use Magento\Framework\Phrase; /** * Abstract resource model class @@ -379,6 +381,7 @@ abstract class AbstractDb extends AbstractResource * @return $this * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @throws \Exception + * @throws AlreadyExistsException * @api */ public function save(\Magento\Framework\Model\AbstractModel $object) @@ -413,6 +416,10 @@ abstract class AbstractDb extends AbstractResource } $this->addCommitCallback([$object, 'afterCommitCallback'])->commit(); $object->setHasDataChanges(false); + } catch (DuplicateException $e) { + $this->rollBack(); + $object->setHasDataChanges(true); + throw new AlreadyExistsException(new Phrase('Unique constraint violation found'), $e); } catch (\Exception $e) { $this->rollBack(); $object->setHasDataChanges(true); diff --git a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/Db/AbstractDbTest.php b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/Db/AbstractDbTest.php index 0a2e6f2262173f244dc0dddf8c53fa44c9bf3558..d13bcdc539aa8c82d7af3b24ea1d32ed93e8431b 100644 --- a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/Db/AbstractDbTest.php +++ b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/Db/AbstractDbTest.php @@ -7,6 +7,10 @@ // @codingStandardsIgnoreFile namespace Magento\Framework\Model\Test\Unit\ResourceModel\Db; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\DB\Adapter\DuplicateException; +use Magento\Framework\Model\AbstractModel; +use Magento\Framework\Model\ResourceModel\Db\AbstractDb; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -14,7 +18,7 @@ namespace Magento\Framework\Model\Test\Unit\ResourceModel\Db; class AbstractDbTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Framework\Model\ResourceModel\Db\AbstractDb + * @var AbstractDb */ protected $_model; @@ -63,7 +67,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase ->willReturn($this->transactionManagerMock); $this->_model = $this->getMockForAbstractClass( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + AbstractDb::class, [$contextMock], '', true, @@ -116,7 +120,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase public function testAddUniqueFieldArray() { $this->assertInstanceOf( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + AbstractDb::class, $this->_model->addUniqueField(['someField']) ); } @@ -134,7 +138,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase { $data = 'MainTableName'; $idFieldNameProperty = new \ReflectionProperty( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, '_idFieldName' + AbstractDb::class, '_idFieldName' ); $idFieldNameProperty->setAccessible(true); $idFieldNameProperty->setValue($this->_model, $data); @@ -158,7 +162,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase public function testGetMainTable($tableName, $expectedResult) { $mainTableProperty = new \ReflectionProperty( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + AbstractDb::class, '_mainTable' ); $mainTableProperty->setAccessible(true); @@ -195,7 +199,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase $this->returnValue('tableName') ); $tablesProperty = new \ReflectionProperty( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + AbstractDb::class, '_tables' ); $tablesProperty->setAccessible(true); @@ -215,7 +219,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase */ public function testGetChecksum($checksum, $expected) { - $connectionMock = $this->getMock(\Magento\Framework\DB\Adapter\AdapterInterface::class, [], [], '', false); + $connectionMock = $this->getMock(AdapterInterface::class, [], [], '', false); $connectionMock->expects($this->once())->method('getTablesChecksum')->with($checksum)->will( $this->returnValue([$checksum => 'checksum']) ); @@ -242,7 +246,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase public function testResetUniqueField() { $uniqueFields = new \ReflectionProperty( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + AbstractDb::class, '_uniqueFields' ); $uniqueFields->setAccessible(true); @@ -254,7 +258,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase public function testGetUniqueFields() { $uniqueFieldsReflection = new \ReflectionProperty( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + AbstractDb::class, '_uniqueFields' ); $uniqueFieldsReflection->setAccessible(true); @@ -281,14 +285,14 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase $this->assertEquals($this->_model, $result); $this->assertInstanceOf( \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, - $result + $result ); } public function testDelete() { $connectionInterfaceMock = $this->getMock( - \Magento\Framework\DB\Adapter\AdapterInterface::class, + AdapterInterface::class, [], [], '', @@ -297,7 +301,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase $contextMock = $this->getMock(\Magento\Framework\Model\Context::class, [], [], '', false); $registryMock = $this->getMock(\Magento\Framework\Registry::class, [], [], '', false); $abstractModelMock = $this->getMockForAbstractClass( - \Magento\Framework\Model\AbstractModel::class, + AbstractModel::class, [$contextMock, $registryMock], '', false, @@ -311,7 +315,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase ); $abstractModelMock->expects($this->once())->method('getData')->willReturn(['data' => 'value']); - $connectionMock = $this->getMock(\Magento\Framework\DB\Adapter\AdapterInterface::class); + $connectionMock = $this->getMock(AdapterInterface::class); $this->transactionManagerMock->expects($this->once()) ->method('start') ->with($connectionInterfaceMock) @@ -334,13 +338,13 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase $this->returnValue('tableName') ); $mainTableReflection = new \ReflectionProperty( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + AbstractDb::class, '_mainTable' ); $mainTableReflection->setAccessible(true); $mainTableReflection->setValue($this->_model, 'tableName'); $idFieldNameReflection = new \ReflectionProperty( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + AbstractDb::class, '_idFieldName' ); $idFieldNameReflection->setAccessible(true); @@ -351,7 +355,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase $abstractModelMock->expects($this->once())->method('afterDelete'); $abstractModelMock->expects($this->once())->method('afterDeleteCommit'); $this->assertInstanceOf( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + AbstractDb::class, $this->_model->delete($abstractModelMock) ); } @@ -361,7 +365,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase $contextMock = $this->getMock(\Magento\Framework\Model\Context::class, [], [], '', false); $registryMock = $this->getMock(\Magento\Framework\Registry::class, [], [], '', false); $abstractModelMock = $this->getMockForAbstractClass( - \Magento\Framework\Model\AbstractModel::class, + AbstractModel::class, [$contextMock, $registryMock], '', false, @@ -381,7 +385,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase public function testGetDataChanged($getOriginData, $expected) { $connectionInterfaceMock = $this->getMock( - \Magento\Framework\DB\Adapter\AdapterInterface::class, + AdapterInterface::class, [], [], '', @@ -393,7 +397,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase $contextMock = $this->getMock(\Magento\Framework\Model\Context::class, [], [], '', false); $registryMock = $this->getMock(\Magento\Framework\Registry::class, [], [], '', false); $abstractModelMock = $this->getMockForAbstractClass( - \Magento\Framework\Model\AbstractModel::class, + AbstractModel::class, [$contextMock, $registryMock], '', false, @@ -402,7 +406,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase ['__wakeup', 'getOrigData', 'getData'] ); $mainTableProperty = new \ReflectionProperty( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + AbstractDb::class, '_mainTable' ); $mainTableProperty->setAccessible(true); @@ -431,13 +435,13 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase public function testPrepareDataForUpdate() { - $connectionMock = $this->getMock(\Magento\Framework\DB\Adapter\AdapterInterface::class, [], [], '', false); + $connectionMock = $this->getMock(AdapterInterface::class, [], [], '', false); $context = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( \Magento\Framework\Model\Context::class ); $registryMock = $this->getMock(\Magento\Framework\Registry::class, [], [], '', false); $resourceMock = $this->getMock( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + AbstractDb::class, [ '_construct', 'getConnection', @@ -449,7 +453,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase false ); $connectionInterfaceMock = $this->getMock( - \Magento\Framework\DB\Adapter\AdapterInterface::class, + AdapterInterface::class, [], [], '', @@ -462,7 +466,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMockForAbstractClass(); $abstractModelMock = $this->getMockForAbstractClass( - \Magento\Framework\Model\AbstractModel::class, + AbstractModel::class, [$context, $registryMock, $resourceMock, $resourceCollectionMock] ); $data = 'tableName'; @@ -474,13 +478,13 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase $this->returnValue('tableName') ); $mainTableReflection = new \ReflectionProperty( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + AbstractDb::class, '_mainTable' ); $mainTableReflection->setAccessible(true); $mainTableReflection->setValue($this->_model, 'tableName'); $idFieldNameReflection = new \ReflectionProperty( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, + AbstractDb::class, '_idFieldName' ); $idFieldNameReflection->setAccessible(true); @@ -540,7 +544,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase /** * Mock SUT so as not to test extraneous logic */ - $model = $this->getMockBuilder(\Magento\Framework\Model\ResourceModel\Db\AbstractDb::class) + $model = $this->getMockBuilder(AbstractDb::class) ->disableOriginalConstructor() ->setMethods(['_prepareDataForSave', 'getIdFieldName', 'getConnection', 'getMainTable']) ->getMockForAbstractClass(); @@ -557,7 +561,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase $reflectionProperty->setValue($model, $pkIncrement); // Mocked behavior - $connectionMock = $this->getMockBuilder(\Magento\Framework\DB\Adapter\AdapterInterface::class) + $connectionMock = $this->getMockBuilder(AdapterInterface::class) ->disableOriginalConstructor() ->setMethods(['lastInsertId']) ->getMockForAbstractClass(); @@ -579,7 +583,7 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase // Only set object id if not PK autoincrement $setIdInvokedCount = $pkIncrement ? 1 : 0; - $inputObject = $this->getMockBuilder(\Magento\Framework\Model\AbstractModel::class) + $inputObject = $this->getMockBuilder(AbstractModel::class) ->disableOriginalConstructor() ->getMock(); $inputObject->expects($this->exactly($setIdInvokedCount))->method('setId'); @@ -591,9 +595,37 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase $reflectionMethod->invokeArgs($model, [$inputObject]); } + /** + * @return array + */ public function saveNewObjectDataProvider() { return [[true], [false]]; } + /** + * @expectedException \Magento\Framework\Exception\AlreadyExistsException + */ + public function testDuplicateExceptionProcessingOnSave() + { + $connection = $this->getMock(AdapterInterface::class); + $connection->expects($this->once())->method('rollback'); + + /** @var AbstractDb|\PHPUnit_Framework_MockObject_MockObject $model */ + $model = $this->getMockBuilder(AbstractDb::class) + ->disableOriginalConstructor() + ->setMethods(['getConnection']) + ->getMockForAbstractClass(); + $model->expects($this->any())->method('getConnection')->willReturn($connection); + + /** @var AbstractModel|\PHPUnit_Framework_MockObject_MockObject $object */ + $object = $this->getMockBuilder(AbstractModel::class) + ->disableOriginalConstructor() + ->getMock(); + $object->expects($this->once())->method('hasDataChanges')->willReturn(true); + $object->expects($this->once())->method('beforeSave')->willThrowException(new DuplicateException()); + $object->expects($this->once())->method('setHasDataChanges')->with(true); + + $model->save($object); + } } diff --git a/lib/internal/Magento/Framework/View/Config.php b/lib/internal/Magento/Framework/View/Config.php index 917f632323ea0cda55ab95b55cd663292b5b31d6..b72fe87c4acc4b7155437bc8b478571caa4e72b2 100644 --- a/lib/internal/Magento/Framework/View/Config.php +++ b/lib/internal/Magento/Framework/View/Config.php @@ -62,7 +62,7 @@ class Config implements \Magento\Framework\View\ConfigInterface if (isset($params['themeModel'])) { /** @var \Magento\Framework\View\Design\ThemeInterface $currentTheme */ $currentTheme = $params['themeModel']; - $key = $currentTheme->getCode(); + $key = $currentTheme->getFullPath(); if (isset($this->viewConfigs[$key])) { return $this->viewConfigs[$key]; } diff --git a/lib/internal/Magento/Framework/View/Test/Unit/ConfigTest.php b/lib/internal/Magento/Framework/View/Test/Unit/ConfigTest.php index 4295b5d3e24e73810f66e1a16e83f1d0cb6e84f1..2a09783c710e4e4c9334079a67025b452d673974 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/ConfigTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/ConfigTest.php @@ -40,17 +40,17 @@ class ConfigTest extends \PHPUnit_Framework_TestCase public function testGetViewConfig() { - $themeCode = 2; + $themeCode = 'area/theme'; $themeMock = $this->getMock( \Magento\Theme\Model\Theme::class, - ['getCode'], + ['getFullPath'], [], '', false ); $themeMock->expects($this->atLeastOnce()) - ->method('getCode') + ->method('getFullPath') ->will($this->returnValue($themeCode)); $params = [ 'themeModel' => $themeMock, diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js index 66b72857d003397b8a756dc6aae9c0de70c58eeb..167903f62c760ca8ce495efe0dc42c98546d161f 100755 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js @@ -357,6 +357,8 @@ define([ // escape special chars in directives url to use it in regular expression var url = this.makeDirectiveUrl('%directive%').replace(/([$^.?*!+:=()\[\]{}|\\])/g, '\\$1'); var reg = new RegExp(url.replace('%directive%', '([a-zA-Z0-9,_-]+)')); + content = decodeURIComponent(content); + return content.gsub(reg, function(match) { return Base64.mageDecode(match[1]); }.bind(this)); diff --git a/setup/src/Magento/Setup/Model/PackagesData.php b/setup/src/Magento/Setup/Model/PackagesData.php index 701393fd9666102147c5921ad1831a69488ba8fb..1fc8e9db2bf64f3874bbfa457eb3384d91425863 100644 --- a/setup/src/Magento/Setup/Model/PackagesData.php +++ b/setup/src/Magento/Setup/Model/PackagesData.php @@ -409,6 +409,7 @@ class PackagesData return in_array( $item['package_type'], [ + \Magento\Setup\Model\Grid\TypeMapper::LANGUAGE_PACKAGE_TYPE, \Magento\Setup\Model\Grid\TypeMapper::MODULE_PACKAGE_TYPE, \Magento\Setup\Model\Grid\TypeMapper::EXTENSION_PACKAGE_TYPE, \Magento\Setup\Model\Grid\TypeMapper::THEME_PACKAGE_TYPE, @@ -491,26 +492,38 @@ class PackagesData return array_keys($packageVersions); } - } else { - $versionsPattern = '/^versions\s*\:\s(.+)$/m'; - - $commandParams = [ - self::PARAM_COMMAND => self::COMPOSER_SHOW, - self::PARAM_PACKAGE => $package, - self::PARAM_AVAILABLE => true - ]; - - $applicationFactory = $this->objectManagerProvider->get() - ->get(\Magento\Framework\Composer\MagentoComposerApplicationFactory::class); - /** @var \Magento\Composer\MagentoComposerApplication $application */ - $application = $applicationFactory->create(); - - $result = $application->runComposerCommand($commandParams); - $matches = []; - preg_match($versionsPattern, $result, $matches); - if (isset($matches[1])) { - return explode(', ', $matches[1]); - } + } + + return $this->getAvailableVersionsFromAllRepositories($package); + } + + /** + * Get available versions of package by "composer show" command + * + * @param string $package + * @return array + * @exception \RuntimeException + */ + private function getAvailableVersionsFromAllRepositories($package) + { + $versionsPattern = '/^versions\s*\:\s(.+)$/m'; + + $commandParams = [ + self::PARAM_COMMAND => self::COMPOSER_SHOW, + self::PARAM_PACKAGE => $package, + self::PARAM_AVAILABLE => true + ]; + + $applicationFactory = $this->objectManagerProvider->get() + ->get(\Magento\Framework\Composer\MagentoComposerApplicationFactory::class); + /** @var \Magento\Composer\MagentoComposerApplication $application */ + $application = $applicationFactory->create(); + + $result = $application->runComposerCommand($commandParams); + $matches = []; + preg_match($versionsPattern, $result, $matches); + if (isset($matches[1])) { + return explode(', ', $matches[1]); } throw new \RuntimeException( diff --git a/setup/src/Magento/Setup/Test/Unit/Model/PackagesDataTest.php b/setup/src/Magento/Setup/Test/Unit/Model/PackagesDataTest.php index 5a7ead384665446fa7fb3dc82dff33d4b9777133..54a297e7dbe43909c0fe9e929aec95a0239beb73 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/PackagesDataTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/PackagesDataTest.php @@ -22,38 +22,96 @@ class PackagesDataTest extends \PHPUnit_Framework_TestCase */ private $packagesData; + /** + * @var ComposerInformation|MockObject + */ + private $composerInformation; + + /** + * @var \Magento\Setup\Model\DateTime\TimeZoneProvider|MockObject + */ + private $timeZoneProvider; + + /** + * @var \Magento\Setup\Model\PackagesAuth|MockObject + */ + private $packagesAuth; + + /** + * @var \Magento\Framework\Filesystem|MockObject + */ + private $filesystem; + + /** + * @var \Magento\Setup\Model\ObjectManagerProvider|MockObject + */ + private $objectManagerProvider; + + /** + * @var \Magento\Setup\Model\Grid\TypeMapper|MockObject + */ + private $typeMapper; + public function setUp() { - $composerInformation = $this->getComposerInformation(); - $timeZoneProvider = $this->getMock(\Magento\Setup\Model\DateTime\TimeZoneProvider::class, [], [], '', false); + $this->composerInformation = $this->getComposerInformation(); + $this->timeZoneProvider = $this->getMockBuilder(\Magento\Setup\Model\DateTime\TimeZoneProvider::class) + ->disableOriginalConstructor() + ->getMock(); $timeZone = $this->getMock(\Magento\Framework\Stdlib\DateTime\Timezone::class, [], [], '', false); - $timeZoneProvider->expects($this->any())->method('get')->willReturn($timeZone); - $packagesAuth = $this->getMock(\Magento\Setup\Model\PackagesAuth::class, [], [], '', false); - $filesystem = $this->getMock(\Magento\Framework\Filesystem::class, [], [], '', false); - $objectManagerProvider = $this->getMock(\Magento\Setup\Model\ObjectManagerProvider::class, [], [], '', false); + $this->timeZoneProvider->expects($this->any())->method('get')->willReturn($timeZone); + $this->packagesAuth = $this->getMock(\Magento\Setup\Model\PackagesAuth::class, [], [], '', false); + $this->filesystem = $this->getMock(\Magento\Framework\Filesystem::class, [], [], '', false); + $this->objectManagerProvider = $this->getMockBuilder(\Magento\Setup\Model\ObjectManagerProvider::class) + ->disableOriginalConstructor() + ->getMock(); $objectManager = $this->getMockForAbstractClass(\Magento\Framework\ObjectManagerInterface::class); - $applicationFactory = $this->getMock( - \Magento\Framework\Composer\MagentoComposerApplicationFactory::class, - [], - [], - '', - false - ); + $appFactory = $this->getMockBuilder(\Magento\Framework\Composer\MagentoComposerApplicationFactory::class) + ->disableOriginalConstructor() + ->getMock(); $application = $this->getMock(\Magento\Composer\MagentoComposerApplication::class, [], [], '', false); $application->expects($this->any()) ->method('runComposerCommand') - ->willReturn('versions: 2.0.1'); - $applicationFactory->expects($this->any())->method('create')->willReturn($application); + ->willReturnMap([ + [ + [ + PackagesData::PARAM_COMMAND => PackagesData::COMPOSER_SHOW, + PackagesData::PARAM_PACKAGE => 'magento/package-1', + PackagesData::PARAM_AVAILABLE => true, + ], + null, + 'versions: 2.0.1' + ], + [ + [ + PackagesData::PARAM_COMMAND => PackagesData::COMPOSER_SHOW, + PackagesData::PARAM_PACKAGE => 'magento/package-2', + PackagesData::PARAM_AVAILABLE => true, + ], + null, + 'versions: 2.0.1' + ], + [ + [ + PackagesData::PARAM_COMMAND => PackagesData::COMPOSER_SHOW, + PackagesData::PARAM_PACKAGE => 'partner/package-3', + PackagesData::PARAM_AVAILABLE => true, + ], + null, + 'versions: 3.0.1' + ], + ]); + $appFactory->expects($this->any())->method('create')->willReturn($application); $objectManager->expects($this->any()) ->method('get') ->with(\Magento\Framework\Composer\MagentoComposerApplicationFactory::class) - ->willReturn($applicationFactory); - $objectManagerProvider->expects($this->any())->method('get')->willReturn($objectManager); + ->willReturn($appFactory); + $this->objectManagerProvider->expects($this->any())->method('get')->willReturn($objectManager); $directoryWrite = $this->getMockForAbstractClass(\Magento\Framework\Filesystem\Directory\WriteInterface::class); $directoryRead = $this->getMockForAbstractClass(\Magento\Framework\Filesystem\Directory\ReadInterface::class); - $filesystem->expects($this->any())->method('getDirectoryRead')->will($this->returnValue($directoryRead)); - $filesystem->expects($this->any()) + $this->filesystem->expects($this->any())->method('getDirectoryRead')->will($this->returnValue($directoryRead)); + $this->filesystem->expects($this->any()) ->method('getDirectoryWrite') ->will($this->returnValue($directoryWrite)); $directoryWrite->expects($this->any())->method('isExist')->willReturn(true); @@ -81,32 +139,41 @@ class PackagesDataTest extends \PHPUnit_Framework_TestCase . '}}}' ); - $typeMapper = $this->getMockBuilder(\Magento\Setup\Model\Grid\TypeMapper::class) + $this->typeMapper = $this->getMockBuilder(\Magento\Setup\Model\Grid\TypeMapper::class) ->disableOriginalConstructor() ->getMock(); - $typeMapper->expects(static::any()) + $this->typeMapper->expects(static::any()) ->method('map') ->willReturnMap([ [ComposerInformation::MODULE_PACKAGE_TYPE, \Magento\Setup\Model\Grid\TypeMapper::MODULE_PACKAGE_TYPE], ]); + $this->createPackagesData(); + } + + private function createPackagesData() + { $this->packagesData = new PackagesData( - $composerInformation, - $timeZoneProvider, - $packagesAuth, - $filesystem, - $objectManagerProvider, - $typeMapper + $this->composerInformation, + $this->timeZoneProvider, + $this->packagesAuth, + $this->filesystem, + $this->objectManagerProvider, + $this->typeMapper ); } /** + * @param array $requiredPackages + * @param array $installedPackages + * @param array $repo * @return ComposerInformation|MockObject */ - private function getComposerInformation() + private function getComposerInformation($requiredPackages = [], $installedPackages = [], $repo = []) { $composerInformation = $this->getMock(ComposerInformation::class, [], [], '', false); $composerInformation->expects($this->any())->method('getInstalledMagentoPackages')->willReturn( + $installedPackages ?: [ 'magento/package-1' => [ 'name' => 'magento/package-1', @@ -117,21 +184,30 @@ class PackagesDataTest extends \PHPUnit_Framework_TestCase 'name' => 'magento/package-2', 'type' => 'magento2-module', 'version'=> '1.0.1' - ] + ], + 'partner/package-3' => [ + 'name' => 'partner/package-3', + 'type' => 'magento2-module', + 'version'=> '3.0.0' + ], ] ); $composerInformation->expects($this->any())->method('getRootRepositories') - ->willReturn(['repo1', 'repo2']); + ->willReturn($repo ?: ['repo1', 'repo2']); $composerInformation->expects($this->any())->method('getPackagesTypes') ->willReturn(['magento2-module']); $rootPackage = $this->getMock(RootPackage::class, [], ['magento/project', '2.1.0', '2']); $rootPackage->expects($this->any()) ->method('getRequires') - ->willReturn([ - 'magento/package-1' => '1.0.0', - 'magento/package-2' => '1.0.1' - ]); + ->willReturn( + $requiredPackages ?: + [ + 'magento/package-1' => '1.0.0', + 'magento/package-2' => '1.0.1', + 'partner/package-3' => '3.0.0', + ] + ); $composerInformation->expects($this->any()) ->method('getRootPackage') ->willReturn($rootPackage); @@ -146,19 +222,57 @@ class PackagesDataTest extends \PHPUnit_Framework_TestCase $this->assertArrayHasKey('date', $latestData['lastSyncDate']); $this->assertArrayHasKey('time', $latestData['lastSyncDate']); $this->assertArrayHasKey('packages', $latestData); - $this->assertSame(2, count($latestData['packages'])); - $this->assertSame(2, $latestData['countOfUpdate']); + $this->assertSame(3, count($latestData['packages'])); + $this->assertSame(3, $latestData['countOfUpdate']); $this->assertArrayHasKey('installPackages', $latestData); $this->assertSame(1, count($latestData['installPackages'])); $this->assertSame(1, $latestData['countOfInstall']); } - public function testGetPackagesForUpdate() + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Couldn't get available versions for package partner/package-4 + */ + public function testGetPackagesForUpdateWithException() { + $requiredPackages = [ + 'partner/package-4' => '4.0.4', + ]; + $installedPackages = [ + 'partner/package-4' => [ + 'name' => 'partner/package-4', + 'type' => 'magento2-module', + 'version'=> '4.0.4' + ], + ]; + $this->composerInformation = $this->getComposerInformation($requiredPackages, $installedPackages); + $this->createPackagesData(); + $this->packagesData->getPackagesForUpdate(); + } + + public function testPackagesForUpdateFromJson() + { + $this->composerInformation = $this->getComposerInformation([], [], ['https://repo1']); + $this->packagesAuth->expects($this->atLeastOnce()) + ->method('getCredentialBaseUrl') + ->willReturn('repo1'); + $this->createPackagesData(); $packages = $this->packagesData->getPackagesForUpdate(); $this->assertEquals(2, count($packages)); $this->assertArrayHasKey('magento/package-1', $packages); + $this->assertArrayHasKey('partner/package-3', $packages); + $firstPackage = array_values($packages)[0]; + $this->assertArrayHasKey('latestVersion', $firstPackage); + $this->assertArrayHasKey('versions', $firstPackage); + } + + public function testGetPackagesForUpdate() + { + $packages = $this->packagesData->getPackagesForUpdate(); + $this->assertEquals(3, count($packages)); + $this->assertArrayHasKey('magento/package-1', $packages); $this->assertArrayHasKey('magento/package-2', $packages); + $this->assertArrayHasKey('partner/package-3', $packages); $firstPackage = array_values($packages)[0]; $this->assertArrayHasKey('latestVersion', $firstPackage); $this->assertArrayHasKey('versions', $firstPackage); @@ -167,9 +281,10 @@ class PackagesDataTest extends \PHPUnit_Framework_TestCase public function testGetInstalledPackages() { $installedPackages = $this->packagesData->getInstalledPackages(); - $this->assertEquals(2, count($installedPackages)); + $this->assertEquals(3, count($installedPackages)); $this->assertArrayHasKey('magento/package-1', $installedPackages); $this->assertArrayHasKey('magento/package-2', $installedPackages); + $this->assertArrayHasKey('partner/package-3', $installedPackages); } public function testGetMetaPackagesMap()