diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php index d402c81becf1ce21e636b6d36082a47ddcc2f155..d59492c4065e72706f8c1a168e4a33b1c2c9e825 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php @@ -199,6 +199,9 @@ class Helper $customOptions = []; foreach ($options as $customOptionData) { if (empty($customOptionData['is_delete'])) { + if (empty($customOptionData['option_id'])) { + $customOptionData['option_id'] = null; + } if (isset($customOptionData['values'])) { $customOptionData['values'] = array_filter($customOptionData['values'], function ($valueData) { return empty($valueData['is_delete']); @@ -206,7 +209,6 @@ class Helper } $customOption = $this->getCustomOptionFactory()->create(['data' => $customOptionData]); $customOption->setProductSku($product->getSku()); - $customOption->setOptionId(null); $customOptions[] = $customOption; } } @@ -255,7 +257,7 @@ class Helper foreach ($linkTypes as $linkType => $readonly) { if (isset($links[$linkType]) && !$readonly) { - foreach ((array) $links[$linkType] as $linkData) { + foreach ((array)$links[$linkType] as $linkData) { if (empty($linkData['id'])) { continue; } @@ -321,9 +323,11 @@ class Helper if (isset($option['values']) && isset($overwriteOptions[$optionId]['values'])) { foreach ($option['values'] as $valueIndex => $value) { - $valueId = $value['option_type_id']; - $value = $this->overwriteValue($valueId, $value, $overwriteOptions[$optionId]['values']); - $option['values'][$valueIndex] = $value; + if (isset($value['option_type_id'])) { + $valueId = $value['option_type_id']; + $value = $this->overwriteValue($valueId, $value, $overwriteOptions[$optionId]['values']); + $option['values'][$valueIndex] = $value; + } } } @@ -347,6 +351,9 @@ class Helper foreach ($overwriteOptions[$optionId] as $fieldName => $overwrite) { if ($overwrite && isset($option[$fieldName]) && isset($option['default_' . $fieldName])) { $option[$fieldName] = $option['default_' . $fieldName]; + if ('title' == $fieldName) { + $option['is_delete_store_title'] = 1; + } } } } diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php index ada156f571b0e60c8ff1a0ada71b308f9b62b38f..f17760237034041764539e533d5f1440b8dad3e4 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php @@ -160,12 +160,13 @@ class CreateHandler implements ExtensionInterface if (in_array($attrData, array_keys($existImages))) { $product->setData($mediaAttrCode . '_label', $existImages[$attrData]['label']); } - - $product->addAttributeUpdate( - $mediaAttrCode, - $product->getData($mediaAttrCode), - $product->getStoreId() - ); + if (!empty($product->getData($mediaAttrCode))) { + $product->addAttributeUpdate( + $mediaAttrCode, + $product->getData($mediaAttrCode), + $product->getStoreId() + ); + } } $product->setData($attrCode, $value); diff --git a/app/code/Magento/Catalog/Model/Product/Option/Repository.php b/app/code/Magento/Catalog/Model/Product/Option/Repository.php index d48bed8e3ccd08718e02c57d764e89c147ebf161..946bebd93c94029907b0ac7ed13dc6c1610b376c 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Repository.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Repository.php @@ -137,10 +137,33 @@ class Repository implements \Magento\Catalog\Api\ProductCustomOptionRepositoryIn if (!$productSku) { throw new CouldNotSaveException(__('ProductSku should be specified')); } + /** @var \Magento\Catalog\Model\Product $product */ $product = $this->productRepository->get($productSku); $metadata = $this->getMetadataPool()->getMetadata(ProductInterface::class); $option->setData('product_id', $product->getData($metadata->getLinkField())); - $option->setOptionId(null); + $option->setData('store_id', $product->getStoreId()); + + if ($option->getOptionId()) { + $options = $product->getOptions(); + if (!$options) { + $options = $this->getProductOptions($product); + } + + $persistedOption = array_filter($options, function ($iOption) use ($option) { + return $option->getOptionId() == $iOption->getOptionId(); + }); + $persistedOption = reset($persistedOption); + + if (!$persistedOption) { + throw new NoSuchEntityException(); + } + $originalValues = $persistedOption->getValues(); + $newValues = $option->getData('values'); + if ($newValues) { + $newValues = $this->markRemovedValues($newValues, $originalValues); + $option->setData('values', $newValues); + } + } $option->save(); return $option; } diff --git a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php index 7c32232b6591aeb9a99a9b63f0b40300cd11dfe4..1c8c5b018ddf3b19642242431205756795fce45f 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php @@ -20,7 +20,6 @@ class SaveHandler implements ExtensionInterface /** * @param OptionRepository $optionRepository - * @param MetadataPool $metadataPool */ public function __construct( OptionRepository $optionRepository @@ -36,15 +35,28 @@ class SaveHandler implements ExtensionInterface */ public function execute($entity, $arguments = []) { + $options = $entity->getOptions(); + $optionIds = []; + + if ($options) { + $optionIds = array_map(function ($option) { + /** @var \Magento\Catalog\Model\Product\Option $option */ + return $option->getOptionId(); + }, $options); + } + /** @var \Magento\Catalog\Api\Data\ProductInterface $entity */ foreach ($this->optionRepository->getProductOptions($entity) as $option) { - $this->optionRepository->delete($option); + if (!in_array($option->getOptionId(), $optionIds)) { + $this->optionRepository->delete($option); + } } - if ($entity->getOptions()) { - foreach ($entity->getOptions() as $option) { + if ($options) { + foreach ($options as $option) { $this->optionRepository->save($option); } } + return $entity; } } diff --git a/app/code/Magento/Catalog/Model/Product/Option/Validator/Select.php b/app/code/Magento/Catalog/Model/Product/Option/Validator/Select.php index ba7103a5eada1acac077ae3ce432e0187e1fbe22..d1a317be7c7e0c2d09cd0b5bbddf6ab3844c96d6 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Validator/Select.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Validator/Select.php @@ -51,6 +51,9 @@ class Select extends DefaultValidator $storeId = $option->getProduct()->getStoreId(); } foreach ($values as $value) { + if (isset($value['is_delete']) && (bool)$value['is_delete']) { + continue; + } $type = isset($value['price_type']) ? $value['price_type'] : null; $price = isset($value['price']) ? $value['price'] : null; $title = isset($value['title']) ? $value['title'] : null; diff --git a/app/code/Magento/Catalog/Model/Product/Option/Value.php b/app/code/Magento/Catalog/Model/Product/Option/Value.php index 55a14e26333547543a14e22b7dcbc0342442596d..55c7c74e9a8e62bf14233f8c8b9b90309adfee66 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Value.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Value.php @@ -200,7 +200,7 @@ class Value extends AbstractModel implements \Magento\Catalog\Api\Data\ProductCu 'store_id', $this->getOption()->getStoreId() ); - $this->unsetData('option_type_id'); + if ($this->getData('is_delete') == '1') { if ($this->getId()) { $this->deleteValues($this->getId()); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option.php index 7b23e5979c8b841d9468f4c93596d4138c24d692..8dcdf441d7b85f014a5b6aa0398aa21592b81932 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option.php @@ -247,14 +247,21 @@ class Option extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb $titleTableName = $this->getTable('catalog_product_option_title'); foreach ([\Magento\Store\Model\Store::DEFAULT_STORE_ID, $object->getStoreId()] as $storeId) { $existInCurrentStore = $this->getColFromOptionTable($titleTableName, (int)$object->getId(), (int)$storeId); - $existInDefaultStore = $this->getColFromOptionTable( - $titleTableName, - (int)$object->getId(), - \Magento\Store\Model\Store::DEFAULT_STORE_ID - ); + $existInDefaultStore = (int)$storeId == \Magento\Store\Model\Store::DEFAULT_STORE_ID ? + $existInCurrentStore : + $this->getColFromOptionTable( + $titleTableName, + (int)$object->getId(), + \Magento\Store\Model\Store::DEFAULT_STORE_ID + ); + if ($object->getTitle()) { + $isDeleteStoreTitle = (bool)$object->getData('is_delete_store_title'); if ($existInCurrentStore) { - if ($object->getStoreId() == $storeId) { + if ($isDeleteStoreTitle && (int)$storeId != \Magento\Store\Model\Store::DEFAULT_STORE_ID) { + $connection->delete($titleTableName, ['option_title_id = ?' => $existInCurrentStore]); + + } elseif ($object->getStoreId() == $storeId) { $data = $this->_prepareDataForTable( new \Magento\Framework\DataObject(['title' => $object->getTitle()]), $titleTableName @@ -270,8 +277,13 @@ class Option extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb } } else { // we should insert record into not default store only of if it does not exist in default store - if (($storeId == \Magento\Store\Model\Store::DEFAULT_STORE_ID && !$existInDefaultStore) - || ($storeId != \Magento\Store\Model\Store::DEFAULT_STORE_ID && !$existInCurrentStore) + if ( + ($storeId == \Magento\Store\Model\Store::DEFAULT_STORE_ID && !$existInDefaultStore) || + ( + $storeId != \Magento\Store\Model\Store::DEFAULT_STORE_ID && + !$existInCurrentStore && + !$isDeleteStoreTitle + ) ) { $data = $this->_prepareDataForTable( new \Magento\Framework\DataObject( diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php index 42456a396178c1a1001c45f49a0150612cdd566f..4f3d65800d9457194f4b26817353cc1e281c0dd7 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php @@ -237,6 +237,11 @@ class Value extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb ); $optionTypeId = $this->getConnection()->fetchOne($select); $existInCurrentStore = $this->getOptionIdFromOptionTable($titleTable, (int)$object->getId(), (int)$storeId); + + if ($storeId != \Magento\Store\Model\Store::DEFAULT_STORE_ID && $object->getData('is_delete_store_title')) { + $object->unsetData('title'); + } + if ($object->getTitle()) { if ($existInCurrentStore) { if ($storeId == $object->getStoreId()) { diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php index 389599f510f08961211d7cc212b757db9620547a..edd654a7393126c61b877d35b36de9077316ec4d 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php @@ -6,10 +6,11 @@ namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\Initialization; use Magento\Catalog\Api\Data\ProductLinkInterfaceFactory; -use Magento\Catalog\Api\ProductRepositoryInterface\Proxy as ProductRepository; use Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper; use Magento\Catalog\Controller\Adminhtml\Product\Initialization\StockDataFilter; use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Option; +use Magento\Catalog\Model\ProductRepository; use Magento\Framework\App\RequestInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Store\Api\Data\StoreInterface; @@ -17,7 +18,6 @@ use Magento\Store\Api\Data\WebsiteInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\Framework\Stdlib\DateTime\Filter\Date as DateFilter; use Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory; -use Magento\Catalog\Api\Data\ProductCustomOptionInterface; use Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks; /** @@ -95,7 +95,7 @@ class HelperTest extends \PHPUnit_Framework_TestCase protected $customOptionFactoryMock; /** - * @var ProductCustomOptionInterface|\PHPUnit_Framework_MockObject_MockObject + * @var Option|\PHPUnit_Framework_MockObject_MockObject */ protected $customOptionMock; @@ -136,8 +136,6 @@ class HelperTest extends \PHPUnit_Framework_TestCase ->getMock(); $this->productMock = $this->getMockBuilder(Product::class) ->setMethods([ - 'setData', - 'addData', 'getId', 'setWebsiteIds', 'isLockedAttribute', @@ -145,7 +143,6 @@ class HelperTest extends \PHPUnit_Framework_TestCase 'getAttributes', 'unlockAttribute', 'getOptionsReadOnly', - 'setOptions', 'setCanSaveCustomOptions', '__sleep', '__wakeup', @@ -159,9 +156,10 @@ class HelperTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); - $this->customOptionMock = $this->getMockBuilder(ProductCustomOptionInterface::class) + $this->customOptionMock = $this->getMockBuilder(Option::class) ->disableOriginalConstructor() - ->getMockForAbstractClass(); + ->setMethods(null) + ->getMock(); $this->productLinksMock = $this->getMockBuilder(ProductLinks::class) ->disableOriginalConstructor() ->getMock(); @@ -196,14 +194,10 @@ class HelperTest extends \PHPUnit_Framework_TestCase */ public function testInitialize() { - $this->customOptionMock->expects($this->once()) - ->method('setProductSku'); - $this->customOptionMock->expects($this->once()) - ->method('setOptionId'); - $optionsData = [ - 'option1' => ['is_delete' => true, 'name' => 'name1', 'price' => 'price1'], - 'option2' => ['is_delete' => false, 'name' => 'name1', 'price' => 'price1'], + 'option1' => ['is_delete' => true, 'name' => 'name1', 'price' => 'price1', 'option_id' => ''], + 'option2' => ['is_delete' => false, 'name' => 'name1', 'price' => 'price1', 'option_id' => '13'], + 'option3' => ['is_delete' => false, 'name' => 'name1', 'price' => 'price1', 'option_id' => '14'] ]; $productData = [ 'stock_data' => ['stock_data'], @@ -277,14 +271,7 @@ class HelperTest extends \PHPUnit_Framework_TestCase ->method('getAttributes') ->willReturn($attributesArray); - $productData['category_ids'] = []; - $productData['website_ids'] = []; - unset($productData['options']); - - $this->productMock->expects($this->once()) - ->method('addData') - ->with($productData); - $this->productMock->expects($this->once()) + $this->productMock->expects($this->any()) ->method('getSku') ->willReturn('sku'); $this->productMock->expects($this->any()) @@ -293,13 +280,25 @@ class HelperTest extends \PHPUnit_Framework_TestCase $this->customOptionFactoryMock->expects($this->any()) ->method('create') - ->with(['data' => $optionsData['option2']]) - ->willReturn($this->customOptionMock); - $this->productMock->expects($this->once()) - ->method('setOptions') - ->with([$this->customOptionMock]); + ->willReturnMap([ + [ + ['data' => $optionsData['option2']], + (clone $this->customOptionMock)->setData($optionsData['option2']) + ], [ + ['data' => $optionsData['option3']], + (clone $this->customOptionMock)->setData($optionsData['option3']) + ] + ]); $this->assertEquals($this->productMock, $this->helper->initialize($this->productMock)); + + $productOptions = $this->productMock->getOptions(); + $this->assertTrue(2 == count($productOptions)); + list($option2, $option3) = $productOptions; + $this->assertTrue($option2->getOptionId() == $optionsData['option2']['option_id']); + $this->assertTrue('sku' == $option2->getData('product_sku')); + $this->assertTrue($option3->getOptionId() == $optionsData['option3']['option_id']); + $this->assertTrue('sku' == $option2->getData('product_sku')); } /** @@ -362,9 +361,9 @@ class HelperTest extends \PHPUnit_Framework_TestCase [ 'option_id' => '5', 'key1' => 'val1', - 'key2' => 'val2', + 'title' => 'val2', 'default_key1' => 'val3', - 'default_key2' => 'val4', + 'default_title' => 'val4', 'values' => [ [ 'option_type_id' => '2', @@ -379,7 +378,7 @@ class HelperTest extends \PHPUnit_Framework_TestCase [ 5 => [ 'key1' => '0', - 'key2' => '1', + 'title' => '1', 'values' => [2 => ['key1' => 1]] ] ], @@ -387,9 +386,10 @@ class HelperTest extends \PHPUnit_Framework_TestCase [ 'option_id' => '5', 'key1' => 'val1', - 'key2' => 'val4', + 'title' => 'val4', 'default_key1' => 'val3', - 'default_key2' => 'val4', + 'default_title' => 'val4', + 'is_delete_store_title' => 1, 'values' => [ [ 'option_type_id' => '2', @@ -413,8 +413,9 @@ class HelperTest extends \PHPUnit_Framework_TestCase [ 'option_type_id' => '2', 'key1' => 'val1', - 'key2' => 'val2', - 'default_key1' => 'val11' + 'title' => 'val2', + 'default_key1' => 'val11', + 'default_title' => 'val22' ] ] ] @@ -423,7 +424,7 @@ class HelperTest extends \PHPUnit_Framework_TestCase 7 => [ 'key1' => '1', 'key2' => '1', - 'values' => [2 => ['key1' => 1, 'key2' => 1]] + 'values' => [2 => ['key1' => 0, 'title' => 1]] ] ], [ @@ -435,9 +436,11 @@ class HelperTest extends \PHPUnit_Framework_TestCase 'values' => [ [ 'option_type_id' => '2', - 'key1' => 'val11', - 'key2' => 'val2', - 'default_key1' => 'val11' + 'key1' => 'val1', + 'title' => 'val22', + 'default_key1' => 'val11', + 'default_title' => 'val22', + 'is_delete_store_title' => 1 ] ] ] diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/RepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/RepositoryTest.php index c461e7a616d81c3e9a72a3031d979b9f44817de1..894596342722d392fd79b51a330341c0b14660f5 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/RepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/RepositoryTest.php @@ -8,6 +8,8 @@ namespace Magento\Catalog\Test\Unit\Model\Product\Option; use \Magento\Catalog\Model\Product\Option\Repository; +use Magento\Catalog\Api\Data\ProductCustomOptionInterface; +use \Magento\Catalog\Model\ResourceModel\Product\Option\CollectionFactory; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -30,10 +32,15 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase protected $optionResourceMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ProductCustomOptionInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $optionMock; + /** + * @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $optionCollectionFactory; + /** * @var \PHPUnit_Framework_MockObject_MockObject */ @@ -71,13 +78,10 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase '', false ); - $optionCollectionFactory = $this->getMock( - \Magento\Catalog\Model\ResourceModel\Product\Option\CollectionFactory::class, - ['create'], - [], - '', - false - ); + $this->optionCollectionFactory = $this->getMockBuilder(CollectionFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); $metadataPool = $this->getMockBuilder(\Magento\Framework\EntityManager\MetadataPool::class) ->disableOriginalConstructor() ->getMock(); @@ -96,7 +100,7 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase $this->optionRepository, [ 'optionFactory' => $optionFactory, - 'optionCollectionFactory' => $optionCollectionFactory, + 'collectionFactory' => $this->optionCollectionFactory, 'metadataPool' => $metadataPool ] ); @@ -240,4 +244,75 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase } } } + + /** + * @expectedException \Magento\Framework\Exception\CouldNotSaveException + * @expectedExceptionMessage ProductSku should be specified + */ + public function testSaveCouldNotSaveException() + { + $this->optionMock->expects($this->once())->method('getProductSku')->willReturn(null); + $this->optionRepository->save($this->optionMock); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + */ + public function testSaveNoSuchEntityException() + { + $productSku = 'simple_product'; + $optionId = 1; + $productOptionId = 2; + $this->optionMock->expects($this->once())->method('getProductSku')->willReturn($productSku); + $this->productRepositoryMock + ->expects($this->once()) + ->method('get') + ->with($productSku) + ->willReturn($this->productMock); + $productOption = clone $this->optionMock; + $this->optionMock->expects($this->any())->method('getOptionId')->willReturn($optionId); + $productOption->expects($this->any())->method('getOptionId')->willReturn($productOptionId); + $this->productMock->expects($this->once())->method('getOptions')->willReturn([$productOption]); + $this->optionRepository->save($this->optionMock); + } + + public function testSave() + { + $productSku = 'simple_product'; + $optionId = 1; + $originalValue1 = $this->getMockBuilder(\Magento\Catalog\Model\Product\Option::class) + ->disableOriginalConstructor() + ->getMock(); + $originalValue2 = clone $originalValue1; + $originalValue3 = clone $originalValue1; + + $originalValue1->expects($this->at(0))->method('getData')->with('option_type_id')->willReturn(10); + $originalValue1->expects($this->once())->method('setData')->with('is_delete', 1); + $originalValue2->expects($this->once())->method('getData')->with('option_type_id')->willReturn(4); + $originalValue3->expects($this->once())->method('getData')->with('option_type_id')->willReturn(5); + + $this->optionMock->expects($this->once())->method('getProductSku')->willReturn($productSku); + $this->productRepositoryMock + ->expects($this->once()) + ->method('get') + ->with($productSku) + ->willReturn($this->productMock); + $this->optionMock->expects($this->any())->method('getOptionId')->willReturn($optionId); + $this->productMock->expects($this->once())->method('getOptions')->willReturn([]); + $this->optionMock->expects($this->once())->method('getData')->with('values')->willReturn([ + ['option_type_id' => 4], + ['option_type_id' => 5] + ]); + $optionCollection = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Product\Option\Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $optionCollection->expects($this->once())->method('getProductOptions')->willReturn([$this->optionMock]); + $this->optionCollectionFactory->expects($this->once())->method('create')->willReturn($optionCollection); + $this->optionMock->expects($this->once())->method('getValues')->willReturn([ + $originalValue1, + $originalValue2, + $originalValue3 + ]); + $this->assertEquals($this->optionMock, $this->optionRepository->save($this->optionMock)); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/SaveHandlerTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/SaveHandlerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..222abadd9fe4b9ff2e6c82a9bd7efc24bf5166de --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/SaveHandlerTest.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Test\Unit\Model\Product\Option; + +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Option; +use \Magento\Catalog\Model\Product\Option\Repository; +use \Magento\Catalog\Model\Product\Option\SaveHandler; + +class SaveHandlerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var SaveHandler|\PHPUnit_Framework_MockObject_MockObject + */ + protected $model; + + /** + * @var Product|\PHPUnit_Framework_MockObject_MockObject + */ + protected $entity; + + /** + * @var Option|\PHPUnit_Framework_MockObject_MockObject + */ + protected $optionMock; + + /** + * @var Repository|\PHPUnit_Framework_MockObject_MockObject + */ + protected $optionRepository; + + public function setUp() + { + $this->entity = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->getMock(); + $this->optionMock = $this->getMockBuilder(Option::class) + ->disableOriginalConstructor() + ->getMock(); + $this->optionRepository = $this->getMockBuilder(Repository::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new SaveHandler($this->optionRepository); + } + + public function testExecute() + { + $this->optionMock->expects($this->any())->method('getOptionId')->willReturn(5); + $this->entity->expects($this->once())->method('getOptions')->willReturn([$this->optionMock]); + + $secondOptionMock = $this->getMockBuilder(Option::class) + ->disableOriginalConstructor() + ->getMock(); + $secondOptionMock->expects($this->once())->method('getOptionId')->willReturn(6); + + $this->optionRepository + ->expects($this->once()) + ->method('getProductOptions') + ->with($this->entity) + ->willReturn([$this->optionMock, $secondOptionMock]); + + $this->optionRepository->expects($this->once())->method('delete'); + $this->optionRepository->expects($this->once())->method('save')->with($this->optionMock); + + $this->assertEquals($this->entity, $this->model->execute($this->entity)); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php index c2b3de0c24cb0736b778efb75d9e722d0fcb47b8..75a2b7c27b4d263d6603438ae9d7c8ab13578e91 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php @@ -87,35 +87,47 @@ class CustomOptionsTest extends AbstractModifierTest $originalData = [ $productId => [ - \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions::DATA_SOURCE_DEFAULT => [ + CustomOptions::DATA_SOURCE_DEFAULT => [ 'title' => 'original' ] ] ]; $options = [ - $this->getProductOptionMock(['title' => 'option1']), + $this->getProductOptionMock(['title' => 'option1', 'store_title' => 'Option Store Title']), $this->getProductOptionMock( - ['title' => 'option2'], + ['title' => 'option2', 'store_title' => null], [ - $this->getProductOptionMock(['title' => 'value1']), - $this->getProductOptionMock(['title' => 'value2']) + $this->getProductOptionMock(['title' => 'value1', 'store_title' => 'Option Value Store Title']), + $this->getProductOptionMock(['title' => 'value2', 'store_title' => null]) ] ) ]; $resultData = [ $productId => [ - \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions::DATA_SOURCE_DEFAULT => [ - 'title' => 'original', - \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions::FIELD_ENABLE => 1, - \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions::GRID_OPTIONS_NAME => [ - ['title' => 'option1'], + CustomOptions::DATA_SOURCE_DEFAULT => [ + CustomOptions::FIELD_TITLE_NAME => 'original', + CustomOptions::FIELD_ENABLE => 1, + CustomOptions::GRID_OPTIONS_NAME => [ [ - 'title' => 'option2', + CustomOptions::FIELD_TITLE_NAME => 'option1', + CustomOptions::FIELD_STORE_TITLE_NAME => 'Option Store Title', + CustomOptions::FIELD_IS_USE_DEFAULT => false + ], [ + CustomOptions::FIELD_TITLE_NAME => 'option2', + CustomOptions::FIELD_STORE_TITLE_NAME => null, + CustomOptions::FIELD_IS_USE_DEFAULT => true, CustomOptions::GRID_TYPE_SELECT_NAME => [ - ['title' => 'value1'], - ['title' => 'value2'] + [ + CustomOptions::FIELD_TITLE_NAME => 'value1', + CustomOptions::FIELD_STORE_TITLE_NAME => 'Option Value Store Title', + CustomOptions::FIELD_IS_USE_DEFAULT => false + ], [ + CustomOptions::FIELD_TITLE_NAME => 'value2', + CustomOptions::FIELD_STORE_TITLE_NAME => null, + CustomOptions::FIELD_IS_USE_DEFAULT => true + ] ] ] ] @@ -154,13 +166,13 @@ class CustomOptionsTest extends AbstractModifierTest */ protected function getProductOptionMock(array $data, array $values = []) { + /** @var ProductOption|\PHPUnit_Framework_MockObject_MockObject $productOptionMock */ $productOptionMock = $this->getMockBuilder(ProductOption::class) ->disableOriginalConstructor() + ->setMethods(['getValues']) ->getMock(); - $productOptionMock->expects($this->any()) - ->method('getData') - ->willReturn($data); + $productOptionMock->setData($data); $productOptionMock->expects($this->any()) ->method('getValues') ->willReturn($values); diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php index 5e6c88a1ba93d43f3ab05236769761aa17fcfb12..780cdbbb00e0a3ac06208e6c70a01708376f071d 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php @@ -68,6 +68,7 @@ class CustomOptions extends AbstractModifier const FIELD_ENABLE = 'affect_product_custom_options'; const FIELD_OPTION_ID = 'option_id'; const FIELD_TITLE_NAME = 'title'; + const FIELD_STORE_TITLE_NAME = 'store_title'; const FIELD_TYPE_NAME = 'type'; const FIELD_IS_REQUIRE_NAME = 'is_require'; const FIELD_SORT_ORDER_NAME = 'sort_order'; @@ -79,6 +80,7 @@ class CustomOptions extends AbstractModifier const FIELD_IMAGE_SIZE_X_NAME = 'image_size_x'; const FIELD_IMAGE_SIZE_Y_NAME = 'image_size_y'; const FIELD_IS_DELETE = 'is_delete'; + const FIELD_IS_USE_DEFAULT = 'is_use_default'; /**#@-*/ /**#@+ @@ -112,7 +114,7 @@ class CustomOptions extends AbstractModifier * @var UrlInterface */ protected $urlBuilder; - + /** * @var ArrayManager */ @@ -162,9 +164,14 @@ class CustomOptions extends AbstractModifier /** @var \Magento\Catalog\Model\Product\Option $option */ foreach ($productOptions as $index => $option) { - $options[$index] = $this->formatPriceByPath(static::FIELD_PRICE_NAME, $option->getData()); + $optionData = $option->getData(); + $optionData[static::FIELD_IS_USE_DEFAULT] = !$option->getData(static::FIELD_STORE_TITLE_NAME); + $options[$index] = $this->formatPriceByPath(static::FIELD_PRICE_NAME, $optionData); $values = $option->getValues() ?: []; + foreach ($values as $value) { + $value->setData(static::FIELD_IS_USE_DEFAULT, !$value->getData(static::FIELD_STORE_TITLE_NAME)); + } /** @var \Magento\Catalog\Model\Product\Option $value */ foreach ($values as $value) { $options[$index][static::GRID_TYPE_SELECT_NAME][] = $this->formatPriceByPath( @@ -529,7 +536,8 @@ class CustomOptions extends AbstractModifier 'component' => 'Magento_Catalog/component/static-type-input', 'valueUpdate' => 'input', 'imports' => [ - 'optionId' => '${ $.provider }:${ $.parentScope }.option_id' + 'optionId' => '${ $.provider }:${ $.parentScope }.option_id', + 'isUseDefault' => '${ $.provider }:${ $.parentScope }.is_use_default' ] ], ], @@ -604,6 +612,7 @@ class CustomOptions extends AbstractModifier 'imports' => [ 'optionId' => '${ $.provider }:${ $.parentScope }.option_id', 'optionTypeId' => '${ $.provider }:${ $.parentScope }.option_type_id', + 'isUseDefault' => '${ $.provider }:${ $.parentScope }.is_use_default' ], 'service' => [ 'template' => 'Magento_Catalog/form/element/helper/custom-option-type-service', @@ -1109,7 +1118,7 @@ class CustomOptions extends AbstractModifier } return $this->localeCurrency; } - + /** * Format price according to the locale of the currency * diff --git a/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/helper/custom-option-type-service.html b/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/helper/custom-option-type-service.html index a3f7970e7420ad52ceb96ed23943f8166d1e2c4a..442d96b5ae4bac2c2954f377bba818448d1284b9 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/helper/custom-option-type-service.html +++ b/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/helper/custom-option-type-service.html @@ -12,6 +12,6 @@ name: 'options_use_default[' + $data.optionId + '][values][' + $data.optionTypeId + '][' + $data.index + ']', 'data-form-part': $data.ns " - ko-checked="isUseDefault"> + ko-checked="$data.isUseDefault"> <label translate="'Use Default Value'" attr="for: $data.uid + '_default'" class="admin__field-label"></label> </div> diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index b37ba530845e579cd5b91970e4255eee1745696d..a0feddec6529441ee5f3530bde7db9636fc88895 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -273,7 +273,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity ValidatorInterface::ERROR_MEDIA_PATH_NOT_ACCESSIBLE => 'Imported resource (image) does not exist in the local media storage', ValidatorInterface::ERROR_MEDIA_URL_NOT_ACCESSIBLE => 'Imported resource (image) could not be downloaded from external resource due to timeout or access permissions', ValidatorInterface::ERROR_INVALID_WEIGHT => 'Product weight is invalid', - ValidatorInterface::ERROR_DUPLICATE_URL_KEY => 'Specified URL key already exists', + ValidatorInterface::ERROR_DUPLICATE_URL_KEY => 'Url key: \'%s\' was already generated for an item with the SKU: \'%s\'. You need to specify the unique URL key manually' ]; /** @@ -2367,7 +2367,17 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity $this->urlKeys[$storeId][$urlPath] = $rowData[self::COL_SKU]; $this->rowNumbers[$storeId][$urlPath] = $rowNum; } else { - $this->addRowError(ValidatorInterface::ERROR_DUPLICATE_URL_KEY, $rowNum); + $message = sprintf( + $this->retrieveMessageTemplate(ValidatorInterface::ERROR_DUPLICATE_URL_KEY), + $urlKey, + $this->urlKeys[$storeId][$urlPath] + ); + $this->addRowError( + ValidatorInterface::ERROR_DUPLICATE_URL_KEY, + $rowNum, + $rowData[self::COL_NAME], + $message + ); } } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli/Setup.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli/Setup.php new file mode 100644 index 0000000000000000000000000000000000000000..ceb84eb46acc97c590440e2f7f5e6031ddc969b4 --- /dev/null +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli/Setup.php @@ -0,0 +1,37 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Mtf\Util\Command\Cli; + +use Magento\Mtf\Util\Command\Cli; + +/** + * Setup Magento for tests executions. + */ +class Setup extends Cli +{ + /** + * Parameter for uninstall Magento command. + */ + const PARAM_SETUP_UNINSTALL = 'setup:uninstall'; + + /** + * Options for uninstall Magento command. + * + * @var array + */ + private $options = ['-n']; + + /** + * Uninstall Magento. + * + * @return void + */ + public function uninstall() + { + parent::execute(Setup::PARAM_SETUP_UNINSTALL, $this->options); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/Attribute.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/Attribute.php deleted file mode 100644 index ca29475c03c90181f7caa0849e11a7639b023158..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/Attribute.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Action; - -use Magento\Mtf\Fixture\FixtureInterface; -use Magento\Mtf\Block\Form; -use Magento\Mtf\Client\Element\SimpleElement; - -/** - * Product attribute massaction edit page. - */ -class Attribute extends Form -{ - /** - * Fill the root form. - * - * @param FixtureInterface $fixture - * @param SimpleElement|null $element - * @return $this - */ - public function fill(FixtureInterface $fixture, SimpleElement $element = null) - { - $data = $fixture->getData(); - $fields = []; - foreach ($data as $name => $dataValue) { - $fields['toggle_' . $name] = 'Yes'; - $fields[$name] = $dataValue; - } - $mapping = $this->dataMapping($fields); - $this->_fill($mapping, $element); - - return $this; - } -} diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/Attribute.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/Attribute.xml deleted file mode 100644 index 59b367e49bd66b8dce3cfb1e25dc4b46f9e2eff8..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/Attribute.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" ?> -<!-- -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<mapping strict="0"> - <wrapper>attributes</wrapper> - <fields> - <toggle_price> - <selector>[name='toggle_price']</selector> - <input>checkbox</input> - </toggle_price> - <price /> - </fields> -</mapping> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/Tab/UpdateAttributeTab.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/Tab/UpdateAttributeTab.php new file mode 100644 index 0000000000000000000000000000000000000000..d61c2001a2096ebaedd895a0c483d5a93a9ae8bd --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/Tab/UpdateAttributeTab.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Action\Tab; + +use Magento\Mtf\Client\Element\SimpleElement; +use Magento\Mtf\Client\Locator; +use Magento\Backend\Test\Block\Widget\Tab; + +/** + * Tab on Product update attributes Form. + */ +class UpdateAttributeTab extends Tab +{ + /** + * Change checkbox. + * + * @var string + */ + private $changeCheckbox = [ + 'selector' => './/./ancestor::div[contains(@class,"control")]' + . '//input[@data-role="toggle-editability-all" or contains(@id, "toggle_")]', + 'strategy' => Locator::SELECTOR_XPATH, + 'input' => 'checkbox', + 'value' => 'Yes', + ]; + + /** + * Fill data into fields in the container. + * + * @param array $fields + * @param SimpleElement|null $contextElement + * @return $this + */ + public function setFieldsData(array $fields, SimpleElement $contextElement = null) + { + $context = ($contextElement === null) ? $this->_rootElement : $contextElement; + $mapping = $this->dataMapping($fields); + foreach ($mapping as $field) { + $this->_fill([$this->changeCheckbox], $context->find($field['selector'], $field['strategy'])); + $this->_fill([$field], $context); + } + + return $this; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/UpdateAttributeForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/UpdateAttributeForm.php new file mode 100644 index 0000000000000000000000000000000000000000..a264c491de43aa6fdfd22eb98793316e79996054 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/UpdateAttributeForm.php @@ -0,0 +1,17 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Action; + +use Magento\Backend\Test\Block\Widget\FormTabs; + +/** + * Product update Attributes Form. + */ +class UpdateAttributeForm extends FormTabs +{ + // +} diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/UpdateAttributeForm.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/UpdateAttributeForm.xml new file mode 100644 index 0000000000000000000000000000000000000000..ba8effd797a3dc85e92601fd7037815ef02c91a9 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Action/UpdateAttributeForm.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" ?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tabs> + <product-details> + <class>Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Action\Tab\UpdateAttributeTab</class> + <selector>#attributes_update_tabs_attributes</selector> + <fields> + <price> + <selector>#price</selector> + </price> + </fields> + </product-details> + <advanced-inventory> + <class>Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Action\Tab\UpdateAttributeTab</class> + <selector>#attributes_update_tabs_inventory</selector> + <fields> + <stock_data> + <selector>#inventory_stock_availability</selector> + <input>select</input> + </stock_data> + </fields> + </advanced-inventory> +</tabs> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Grid.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Grid.php index d5e81ad56fd3290ef906c8cb141da8e583757c24..db73f7cc87f177fb1eb05f0184b238cb82cd47f1 100755 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Grid.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Grid.php @@ -7,6 +7,7 @@ namespace Magento\Catalog\Test\Block\Adminhtml\Product; use Magento\Ui\Test\Block\Adminhtml\DataGrid; +use Magento\Mtf\Fixture\FixtureInterface; /** * Backend catalog product grid. @@ -72,12 +73,17 @@ class Grid extends DataGrid /** * Update attributes for selected items. * - * @param array $items [optional] + * @param array $items * @return void */ public function updateAttributes(array $items = []) { - $this->massaction($items, 'Update attributes'); + $products = []; + /** @var FixtureInterface $product */ + foreach ($items as $product) { + $products[] = ["sku" => $product->getSku()]; + } + $this->massaction($products, 'Update attributes'); } /** diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertMassProductUpdateSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertMassProductUpdateSuccessMessage.php index 1666244802ed2e81c5375c2d41b0df0dff0a0191..df326a9ca0023a3c3fbeb45a2c960e88d9fffc32 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertMassProductUpdateSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertMassProductUpdateSuccessMessage.php @@ -23,13 +23,12 @@ class AssertMassProductUpdateSuccessMessage extends AbstractConstraint * Assert that after mass update successful message appears. * * @param CatalogProductIndex $productGrid - * @param array $products + * @param int $productsCount * @return void */ - public function processAssert(CatalogProductIndex $productGrid, $products = []) + public function processAssert(CatalogProductIndex $productGrid, $productsCount) { - $countProducts = count($products) ? count($products) : 1; - $expectedMessage = sprintf(self::SUCCESS_MESSAGE, $countProducts); + $expectedMessage = sprintf(self::SUCCESS_MESSAGE, $productsCount); $actualMessage = $productGrid->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( $expectedMessage, diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductsInStock.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductsInStock.php new file mode 100644 index 0000000000000000000000000000000000000000..f485076d5c018b97dfc67624d505bb617929b901 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductsInStock.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Test\Constraint; + +use Magento\Catalog\Test\Page\Product\CatalogProductView; +use Magento\Mtf\Client\BrowserInterface; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Assert that all products are in stock. + */ +class AssertProductsInStock extends AbstractConstraint +{ + /** + * Assert that In Stock status is displayed for products. + * + * @param CatalogProductView $catalogProductView + * @param BrowserInterface $browser + * @param AssertProductInStock $assertProductInStock + * @param array $products + * @return void + */ + public function processAssert( + CatalogProductView $catalogProductView, + BrowserInterface $browser, + AssertProductInStock $assertProductInStock, + array $products + ) { + foreach ($products as $product) { + $assertProductInStock->processAssert($catalogProductView, $browser, $product); + } + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString() + { + return 'In stock control is visible for each product.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductActionAttributeEdit.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductActionAttributeEdit.xml index e875bdc0817e9bcd97b4c933de90ede7498aec7a..1ff06177a5a20b716f1a24201a785c1ff12eecd6 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductActionAttributeEdit.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductActionAttributeEdit.xml @@ -7,7 +7,7 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/pages.xsd"> <page name="CatalogProductActionAttributeEdit" area="Adminhtml" mca="catalog/product_action_attribute/edit" module="Magento_Catalog"> - <block name="attributesBlockForm" class="Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Action\Attribute" locator="body" strategy="css selector" /> + <block name="attributesBlockForm" class="Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Action\UpdateAttributeForm" locator="body" strategy="css selector" /> <block name="formPageActions" class="Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Action\FormPageActions" locator=".page-main-actions" strategy="css selector" /> </page> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/TierPrice.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/TierPrice.xml index bdfb5deabe5c2828b947130284f0308353fa6bdc..412818cbe40e71634eb1e635d8dc8e1630913b49 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/TierPrice.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/TierPrice.xml @@ -66,5 +66,16 @@ </item> </field> </dataset> + + <dataset name="not_logged_in"> + <field name="0" xsi:type="array"> + <item name="price" xsi:type="string">90</item> + <item name="website" xsi:type="string">All Websites [USD]</item> + <item name="price_qty" xsi:type="string">2</item> + <item name="customer_group" xsi:type="array"> + <item name="dataset" xsi:type="string">NOT_LOGGED_IN</item> + </item> + </field> + </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml index 77d4ee802e1373570a77f5e136c18c5ba393ae4d..9e410c525deef720573e7c93e0de4d463b9b2ac7 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml @@ -168,7 +168,7 @@ <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data> <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data> <data name="product/data/sku" xsi:type="string">simple_sku_%isolation%</data> - <data name="product/data/price/value" xsi:type="string">10008</data> + <data name="product/data/price/value" xsi:type="string">10008.88</data> <data name="product/data/short_description" xsi:type="string">Simple Product short_description %isolation%</data> <data name="product/data/description" xsi:type="string">Simple Product description %isolation%</data> <data name="product/data/weight" xsi:type="string">58</data> @@ -461,6 +461,28 @@ <data name="product/data/country_of_manufacture" xsi:type="string">Antarctica</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" /> </variation> + <variation name="CreateSimpleProductEntityTestVariation28" summary="Create product with tier price for not logged in customer"> + <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data> + <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data> + <data name="product/data/sku" xsi:type="string">simple_sku_%isolation%</data> + <data name="product/data/price/value" xsi:type="string">100</data> + <data name="product/data/weight" xsi:type="string">50</data> + <data name="product/data/quantity_and_stock_status/qty" xsi:type="string">667</data> + <data name="product/data/tier_price/dataset" xsi:type="string">not_logged_in</data> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductTierPriceOnProductPage" /> + </variation> + <variation name="CreateSimpleProductEntityTestVariation29" summary="Create Simple Product and assign it to custom website"> + <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data> + <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data> + <data name="product/data/sku" xsi:type="string">simple_sku_%isolation%</data> + <data name="product/data/price/value" xsi:type="string">200.20</data> + <data name="product/data/weight" xsi:type="string">50</data> + <data name="product/data/quantity_and_stock_status/qty" xsi:type="string">668</data> + <data name="product/data/website_ids/0/dataset" xsi:type="string">custom_store</data> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductOnCustomWebsite" /> + </variation> <variation name="CreateSimpleProductEntityWithEmptySkuMaskTest1" summary="Create Simple Product Entity With Empty Sku Mask" ticketId="MAGETWO-58951"> <data name="configData" xsi:type="string">empty_product_mask_sku</data> <data name="description" xsi:type="string">Create product with custom options(fixed price)</data> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/MassProductUpdateTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/MassProductUpdateTest.php index f7fd82e3342bfdce8760c253215ad8189ef33643..9c38ff1b479fe6a02f2217572bea170b1906f00d 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/MassProductUpdateTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/MassProductUpdateTest.php @@ -6,10 +6,13 @@ namespace Magento\Catalog\Test\TestCase\Product; +use Magento\Mtf\Fixture\FixtureFactory; +use Magento\Mtf\Fixture\FixtureInterface; use Magento\Mtf\TestCase\Injectable; use Magento\Catalog\Test\Fixture\CatalogProductSimple; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductActionAttributeEdit; +use Magento\Mtf\TestStep\TestStepFactory; /** * Precondition: @@ -58,35 +61,58 @@ class MassProductUpdateTest extends Injectable */ protected $configData; + /** + * Factory for Test Steps. + * + * @var TestStepFactory + */ + private $testStepFactory; + + /** + * Factory for Fixtures. + * + * @var FixtureFactory + */ + private $fixtureFactory; + /** * Injection data. * * @param CatalogProductIndex $productGrid * @param CatalogProductActionAttributeEdit $attributeMassActionPage + * @param TestStepFactory $testStepFactory + * @param FixtureFactory $fixtureFactory * @return void */ public function __inject( CatalogProductIndex $productGrid, - CatalogProductActionAttributeEdit $attributeMassActionPage + CatalogProductActionAttributeEdit $attributeMassActionPage, + TestStepFactory $testStepFactory, + FixtureFactory $fixtureFactory ) { $this->productGrid = $productGrid; $this->attributeMassActionPage = $attributeMassActionPage; + $this->testStepFactory = $testStepFactory; + $this->fixtureFactory = $fixtureFactory; } /** * Run mass update product simple entity test. * - * @param CatalogProductSimple $initialProduct * @param CatalogProductSimple $product * @param string $configData + * @param array $initialProducts * @return array */ - public function test(CatalogProductSimple $initialProduct, CatalogProductSimple $product, $configData) + public function test(CatalogProductSimple $product, $configData, array $initialProducts) { $this->configData = $configData; // Preconditions - $initialProduct->persist(); + $products = $this->testStepFactory->create( + \Magento\Catalog\Test\TestStep\CreateProductsStep::class, + ['products' => $initialProducts] + )->run()['products']; $this->objectManager->create( \Magento\Config\Test\TestStep\SetupConfigurationStep::class, @@ -95,19 +121,33 @@ class MassProductUpdateTest extends Injectable // Steps $this->productGrid->open(); - $this->productGrid->getProductGrid()->updateAttributes([['sku' => $initialProduct->getSku()]]); + $this->productGrid->getProductGrid()->updateAttributes($products); $this->attributeMassActionPage->getAttributesBlockForm()->fill($product); $this->attributeMassActionPage->getFormPageActions()->save(); - $data = array_merge($initialProduct->getData(), $product->getData()); - $product = $this->objectManager->create( - \Magento\Catalog\Test\Fixture\CatalogProductSimple::class, - ['data' => $data] - ); - - return [ - 'category' => $initialProduct->getDataFieldConfig('category_ids')['source']->getCategories()[0], - 'product' => $product, - ]; + $updatedProducts = $this->prepareUpdatedProducts($products, $product); + + return ['products' => $updatedProducts]; + } + + /** + * Prepare updated products. + * + * @param array $products + * @param CatalogProductSimple $product + * @return array + */ + private function prepareUpdatedProducts(array $products, CatalogProductSimple $product) + { + $productsReturn = []; + /** @var FixtureInterface $item */ + foreach ($products as $item) { + $productsReturn[] = $this->fixtureFactory->create( + get_class($item), + ['data' => array_merge($item->getData(), $product->getData())] + ); + } + + return $productsReturn; } /** diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/MassProductUpdateTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/MassProductUpdateTest.xml index 6f937999f3c34cc172b3552b6280b7563d07a1d1..5435ea89669f6f1a3d0d3d98cb8e1a5bb5aabed0 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/MassProductUpdateTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/MassProductUpdateTest.xml @@ -9,11 +9,12 @@ <testCase name="Magento\Catalog\Test\TestCase\Product\MassProductUpdateTest" summary="Edit Products Using Mass Actions" ticketId="MAGETWO-21128"> <variation name="MassProductPriceUpdateTestVariation1"> <data name="configData" xsi:type="string">product_flat</data> - <data name="initialProduct/dataset" xsi:type="string">simple_10_dollar</data> + <data name="initialProducts/0" xsi:type="string">catalogProductSimple::simple_10_dollar</data> + <data name="initialProducts/1" xsi:type="string">catalogProductSimple::simple_10_dollar</data> + <data name="productsCount" xsi:type="number">2</data> <data name="product/data/price/value" xsi:type="string">1.99</data> <constraint name="Magento\Catalog\Test\Constraint\AssertMassProductUpdateSuccessMessage" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductInGrid" /> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductInCategory" /> </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.xml index 323246949d1a55825bfe49317af6662be585d15c..0395f9f5ed8cf83c0aa570252cc5ed7df32da3c8 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.xml @@ -145,5 +145,19 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductInGrid" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductInCategory" /> </variation> + <variation name="EditSimpleProductTestVariation11" summary="Update simple product with custom option"> + <data name="initialProduct/dataset" xsi:type="string">product_with_category</data> + <data name="product/data/name" xsi:type="string">Test simple product %isolation%</data> + <data name="product/data/sku" xsi:type="string">test_simple_product_%isolation%</data> + <data name="product/data/price/value" xsi:type="string">245.00</data> + <data name="product/data/quantity_and_stock_status/qty" xsi:type="string">200</data> + <data name="product/data/custom_options/dataset" xsi:type="string">drop_down_with_one_option_percent_price</data> + <data name="product/data/checkout_data/dataset" xsi:type="string">simple_drop_down_with_one_option_percent_price</data> + <data name="product/data/url_key" xsi:type="string">test-simple-product-%isolation%</data> + <data name="product/data/weight" xsi:type="string">120.0000</data> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductForm" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductInCart" /> + </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php index e8178d07a1e9e26b6494d0b06551149636e4e4c1..697733fd3c33d8856f5d775452aca8ad977e77e9 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php @@ -129,7 +129,7 @@ class Cart extends Block Locator::SELECTOR_XPATH ); $cartItem = $this->blockFactory->create( - \Magento\Checkout\Test\Block\Cart\CartItem::class, + '\\' . get_class($this) . '\CartItem', ['element' => $cartItemBlock] ); } diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Totals.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Totals.php index 2cf6d5ad87dfff1d9f5c96b9ed40414abb822d44..240ae1c183201f2c479564b5dfad59a274e84b9d 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Totals.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Totals.php @@ -240,7 +240,7 @@ class Totals extends Block */ public function isVisibleShippingPriceBlock() { - return $this->_rootElement->find($this->shippingPriceBlockSelector, Locator::SELECTOR_CSS)->isVisible(); + return $this->_rootElement->find($this->shippingPriceBlockSelector, Locator::SELECTOR_CSS)->isVisible(); } /** diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Grid.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Grid.php new file mode 100644 index 0000000000000000000000000000000000000000..e6fa3271ea6cd60d1f8ae7e509a3c873344e7e7d --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Grid.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product; + +use Magento\ConfigurableProduct\Test\Fixture\ConfigurableProduct; + +/** + * Backend catalog product grid. + */ +class Grid extends \Magento\Catalog\Test\Block\Adminhtml\Product\Grid +{ + /** + * Prepare data. + * + * @param ConfigurableProduct $product + * @return array + */ + public function prepareData($product) + { + $configurableAttributesData = $product->getConfigurableAttributesData(); + $productItems[] = ['sku' => $product->getSku()]; + foreach ($configurableAttributesData['matrix'] as $variation) { + $productItems[] = ['sku' => $variation['sku']]; + } + + return $productItems; + } +} diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct.xml index 2a3703a10607554c2682f19b036201cc700dc477..4a69a7604bca3d74119b07bdcea3b2115a1f6648 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct.xml @@ -41,6 +41,35 @@ </field> </dataset> + <dataset name="out_of_stock"> + <field name="name" xsi:type="string">Test configurable product %isolation%</field> + <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field> + <field name="price" xsi:type="array"> + <item name="value" xsi:type="string">40</item> + <item name="dataset" xsi:type="string">price_40</item> + </field> + <field name="status" xsi:type="string">Yes</field> + <field name="visibility" xsi:type="string">Catalog, Search</field> + <field name="tax_class_id" xsi:type="array"> + <item name="dataset" xsi:type="string">taxable_goods</item> + </field> + <field name="url_key" xsi:type="string">configurable-product-%isolation%</field> + <field name="configurable_attributes_data" xsi:type="array"> + <item name="dataset" xsi:type="string">two_options_with_assigned_product</item> + </field> + <field name="quantity_and_stock_status" xsi:type="array"> + <item name="is_in_stock" xsi:type="string">Out of Stock</item> + </field> + <field name="website_ids" xsi:type="array"> + <item name="0" xsi:type="array"> + <item name="dataset" xsi:type="string">default</item> + </item> + </field> + <field name="attribute_set_id" xsi:type="array"> + <item name="dataset" xsi:type="string">default</item> + </field> + </dataset> + <dataset name="configurable_with_qty_1"> <field name="name" xsi:type="string">Test configurable product %isolation%</field> <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/MassProductUpdateTest.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/MassProductUpdateTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..3d58645d618ffe4f34beb84cd3a1d58212649148 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/MassProductUpdateTest.xml @@ -0,0 +1,21 @@ +<?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\Catalog\Test\TestCase\Product\MassProductUpdateTest" summary="Edit Products Using Mass Actions" ticketId="MAGETWO-21128"> + <variation name="MassProductUpdateTestVariation2" summary="Update stock data for simple and configurable"> + <data name="configData" xsi:type="string">product_flat</data> + <data name="initialProducts/1" xsi:type="string">configurableProduct::out_of_stock</data> + <data name="initialProducts/0" xsi:type="string">catalogProductSimple::out_of_stock</data> + <data name="productsCount" xsi:type="number">2</data> + <data name="product/data/stock_data" xsi:type="string">In Stock</data> + <constraint name="Magento\Catalog\Test\Constraint\AssertMassProductUpdateSuccessMessage" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductInGrid" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductsInStock" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/Devdocs.php b/dev/tests/functional/tests/app/Magento/Install/Test/Block/Devdocs.php new file mode 100644 index 0000000000000000000000000000000000000000..1be88c0bbf7b89f7dbf529456a9ee1235df1e163 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/Devdocs.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Install\Test\Block; + +use Magento\Mtf\Block\Block; + +/** + * Developer Documentation block. + */ +class Devdocs extends Block +{ + /** + * Developer Documentation title. + * + * @var string + */ + protected $devdocsTitle = '.page-heading'; + + /** + * Get Developer Documentation title text. + * + * @return string + */ + public function getDevdocsTitle() + { + return $this->_rootElement->find($this->devdocsTitle)->getText(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/Landing.php b/dev/tests/functional/tests/app/Magento/Install/Test/Block/Landing.php index 5b92b332b26960fdfc0e285459e39b78f5c72f67..d809fb861b66c92138a3231aeae8a7bd35ea15d9 100644 --- a/dev/tests/functional/tests/app/Magento/Install/Test/Block/Landing.php +++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/Landing.php @@ -14,6 +14,13 @@ use Magento\Mtf\Client\Locator; */ class Landing extends Block { + /** + * Link by text. + * + * @var string + */ + protected $linkSelector = '//a[text()="%s"]'; + /** * 'Agree and Set up Magento' button. * @@ -47,4 +54,15 @@ class Landing extends Block { $this->_rootElement->find($this->termsAndAgreement, Locator::SELECTOR_CSS)->click(); } + + /** + * Click on link. + * + * @param string $text + * @return void + */ + public function clickLink($text) + { + $this->_rootElement->find(sprintf($this->linkSelector, $text), Locator::SELECTOR_XPATH)->click(); + } } diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertDevdocsLink.php b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertDevdocsLink.php new file mode 100644 index 0000000000000000000000000000000000000000..d397cc1882b6f39c2fa5423a9ccecbceec002aaa --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertDevdocsLink.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Install\Test\Constraint; + +use Magento\Install\Test\Page\DevdocsInstall; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Check Developer Documentation link. + */ +class AssertDevdocsLink extends AbstractConstraint +{ + /** + * Developer Documentation title. + */ + const DEVDOCS_TITLE_TEXT = 'Setup Wizard installation'; + + /** + * Check Developer Documentation link. + * + * @param DevdocsInstall $devdocsInstallPage + * @return void + */ + public function processAssert(DevdocsInstall $devdocsInstallPage) + { + \PHPUnit_Framework_Assert::assertEquals( + self::DEVDOCS_TITLE_TEXT, + $devdocsInstallPage->getDevdocsBlock()->getDevdocsTitle(), + 'Developer Documentation link is wrong.' + ); + } + + /** + * Returns a string representation of successful assertion. + * + * @return string + */ + public function toString() + { + return "Developer Documentation link is correct."; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Page/DevdocsInstall.xml b/dev/tests/functional/tests/app/Magento/Install/Test/Page/DevdocsInstall.xml new file mode 100644 index 0000000000000000000000000000000000000000..d2dc975cc2b2bd82a72b6b9e4e1d71b97fd635b4 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Install/Test/Page/DevdocsInstall.xml @@ -0,0 +1,12 @@ +<?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/pages.xsd"> + <page name="DevdocsInstall" mca="http://devdocs.magento.com/guides/v2.0/install-gde/install/web/install-web.html" module="Magento_Install"> + <block name="devdocsBlock" class="Magento\Install\Test\Block\Devdocs" locator="body" strategy="css selector"/> + </page> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.php b/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.php index f7931b03e3def69ddb02f6c73c7c0381fd8cf0c1..ee51c4eee82271b2744d63167d56b82e526049a9 100644 --- a/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.php +++ b/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.php @@ -7,6 +7,7 @@ namespace Magento\Install\Test\TestCase; use Magento\Install\Test\Page\Install; +use Magento\Install\Test\Page\DevdocsInstall; use Magento\Install\Test\Fixture\Install as InstallConfig; use Magento\User\Test\Fixture\User; use Magento\Mtf\Fixture\FixtureFactory; @@ -14,6 +15,9 @@ use Magento\Mtf\TestCase\Injectable; use Magento\Install\Test\Constraint\AssertAgreementTextPresent; use Magento\Install\Test\Constraint\AssertSuccessfulReadinessCheck; use Magento\Install\Test\Constraint\AssertAdminUriAutogenerated; +use Magento\Install\Test\Constraint\AssertDevdocsLink; +use Magento\Mtf\Util\Command\Cli\Setup; +use Magento\Mtf\Client\BrowserInterface; /** * PLEASE ADD NECESSARY INFO BEFORE RUNNING TEST TO @@ -24,24 +28,47 @@ use Magento\Install\Test\Constraint\AssertAdminUriAutogenerated; * * Steps: * 1. Go setup landing page. - * 2. Click on "Terms and agreements" button. - * 3. Check license agreement text. - * 4. Return back to landing page and click "Agree and Setup" button. - * 5. Click "Start Readiness Check" button. - * 6. Make sure PHP Version, PHP Extensions and File Permission are ok. - * 7. Click "Next" and fill DB credentials. - * 8. Click "Test Connection and Authentication" and make sure connection successful. - * 9. Click "Next" and fill store address and admin path. - * 10. Click "Next" and leave all default values. - * 11. Click "Next" and fill admin user info. - * 12. Click "Next" and on the "Step 6: Install" page click "Install Now" button. - * 13. Perform assertions. + * 2. Click on Developer Documentation link. + * 3. Check Developer Documentation title. + * 4. Click on "Terms and agreements" button. + * 5. Check license agreement text. + * 6. Return back to landing page and click "Agree and Setup" button. + * 7. Click "Start Readiness Check" button. + * 8. Make sure PHP Version, PHP Extensions and File Permission are ok. + * 9. Click "Next" and fill DB credentials. + * 10. Click "Test Connection and Authentication" and make sure connection successful. + * 11. Click "Next" and fill store address and admin path. + * 12. Click "Next" and leave all default values. + * 13. Click "Next" and fill admin user info. + * 14. Click "Next" and on the "Step 6: Install" page click "Install Now" button. + * 15. Perform assertions. * * @group Installer_and_Upgrade/Downgrade * @ZephyrId MAGETWO-31431 + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class InstallTest extends Injectable { + /** + * Developer Documentation link text. + */ + const DEVDOCS_LINK_TEXT = 'Getting Started'; + + /** + * Developer Documentation install page. + * + * @var DevdocsInstall + */ + protected $devdocsInstallPage; + + /** + * Terms and agreement selector. + * + * @var string + */ + protected $termsLink = '.text-terms>a'; + /** * Install page. * @@ -72,14 +99,16 @@ class InstallTest extends Injectable * Uninstall Magento. * * @param Install $installPage + * @param Setup $magentoSetup + * @param DevdocsInstall $devdocsInstallPage * @return void */ - public function __inject(Install $installPage) + public function __inject(Install $installPage, Setup $magentoSetup, DevdocsInstall $devdocsInstallPage) { - $magentoBaseDir = dirname(dirname(dirname(MTF_BP))); // Uninstall Magento. - shell_exec("php -f $magentoBaseDir/bin/magento setup:uninstall -n"); + $magentoSetup->uninstall(); $this->installPage = $installPage; + $this->devdocsInstallPage = $devdocsInstallPage; } /** @@ -91,6 +120,8 @@ class InstallTest extends Injectable * @param AssertAgreementTextPresent $assertLicense * @param AssertSuccessfulReadinessCheck $assertReadiness * @param AssertAdminUriAutogenerated $assertAdminUri + * @param AssertDevdocsLink $assertDevdocsLink + * @param BrowserInterface $browser * @param array $install [optional] * @return array */ @@ -101,6 +132,8 @@ class InstallTest extends Injectable AssertAgreementTextPresent $assertLicense, AssertSuccessfulReadinessCheck $assertReadiness, AssertAdminUriAutogenerated $assertAdminUri, + AssertDevdocsLink $assertDevdocsLink, + BrowserInterface $browser, array $install = [] ) { $dataConfig = array_merge($install, $configData); @@ -111,6 +144,14 @@ class InstallTest extends Injectable $installConfig = $fixtureFactory->create(\Magento\Install\Test\Fixture\Install::class, ['data' => $dataConfig]); // Steps $this->installPage->open(); + // Verify Developer Documentation link. + $handle = $browser->getCurrentWindow(); + $this->installPage->getLandingBlock()->clickLink(self::DEVDOCS_LINK_TEXT); + $this->waitTillTermsLinkNotVisible($browser); + $docHandle = $browser->getCurrentWindow(); + $assertDevdocsLink->processAssert($this->devdocsInstallPage); + $browser->closeWindow($docHandle); + $browser->selectWindow($handle); // Verify license agreement. $this->installPage->getLandingBlock()->clickTermsAndAgreement(); $assertLicense->processAssert($this->installPage); @@ -139,4 +180,20 @@ class InstallTest extends Injectable return ['installConfig' => $installConfig]; } + + /** + * Wait till terms link is not visible. + * + * @param BrowserInterface $browser + * @return void + */ + private function waitTillTermsLinkNotVisible(BrowserInterface $browser) + { + $browser->waitUntil( + function () use ($browser) { + $browser->selectWindow(); + return $browser->find($this->termsLink)->isVisible() ? null : true; + } + ); + } } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create.php index ae6631eff9a24c9f323bee5bdc91b99dc355972b..b86ac18ea3dd4a70a5b3ba2530edbf89cfe1068c 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create.php @@ -279,25 +279,40 @@ class Create extends Block } /** - * Fill addresses based on present data in customer and order fixtures. + * Fill Billing Address. * - * @param FixtureInterface $address - * @param string $saveAddress + * @param FixtureInterface $billingAddress + * @param string $saveAddress [optional] * @param bool $setShippingAddress [optional] * @return void */ - public function fillAddresses(FixtureInterface $address, $saveAddress = 'No', $setShippingAddress = true) - { + public function fillBillingAddress( + FixtureInterface $billingAddress, + $saveAddress = 'No', + $setShippingAddress = true + ) { if ($setShippingAddress) { $this->getShippingAddressBlock()->uncheckSameAsBillingShippingAddress(); } - $this->browser->find($this->header)->hover(); - $this->getBillingAddressBlock()->fill($address); + $this->getBillingAddressBlock()->fill($billingAddress); $this->getBillingAddressBlock()->saveInAddressBookBillingAddress($saveAddress); $this->getTemplateBlock()->waitLoader(); - if ($setShippingAddress) { + } + + /** + * Fill Shipping Address. + * + * @param FixtureInterface $shippingAddress [optional] + * @return void + */ + public function fillShippingAddress(FixtureInterface $shippingAddress = null) + { + if (!$shippingAddress) { $this->getShippingAddressBlock()->setSameAsBillingShippingAddress(); $this->getTemplateBlock()->waitLoader(); + } else { + $this->getShippingAddressBlock()->fill($shippingAddress); + $this->getTemplateBlock()->waitLoader(); } } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Shipping/Address.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Shipping/Address.php index 044286ea1434a369b31074b739b8ee998b405c8f..f52d898d232d145c117911d77968431001eeba70 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Shipping/Address.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Shipping/Address.php @@ -9,6 +9,7 @@ namespace Magento\Sales\Test\Block\Adminhtml\Order\Create\Shipping; use Magento\Mtf\Block\Form; use Magento\Mtf\Client\Locator; use Magento\Backend\Test\Block\Template; +use Magento\Mtf\Client\Element\SimpleElement; /** * Adminhtml sales order create shipping address block. @@ -29,6 +30,13 @@ class Address extends Form */ protected $sameAsBilling = '#order-shipping_same_as_billing'; + /** + * Wait element. + * + * @var string + */ + private $waitElement = '.loading-mask'; + /** * Shipping address title selector. * @@ -95,4 +103,41 @@ class Address extends Form ['element' => $this->_rootElement->find($this->templateBlock, Locator::SELECTOR_XPATH)] ); } + + /** + * Fill specified form data. + * + * @param array $fields + * @param SimpleElement $element + * @return void + * @throws \Exception + */ + protected function _fill(array $fields, SimpleElement $element = null) + { + $context = ($element === null) ? $this->_rootElement : $element; + foreach ($fields as $name => $field) { + $this->waitFormLoading(); + $element = $this->getElement($context, $field); + if (!$element->isDisabled()) { + $element->setValue($field['value']); + } else { + throw new \Exception("Unable to set value to field '$name' as it's disabled."); + } + } + } + + /** + * Wait for form loading. + * + * @return void + */ + private function waitFormLoading() + { + $this->_rootElement->click(); + $this->browser->waitUntil( + function () { + return $this->browser->find($this->waitElement)->isVisible() ? null : true; + } + ); + } } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Shipping/Address.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Shipping/Address.xml new file mode 100644 index 0000000000000000000000000000000000000000..2dc30a686c0d9c3b997f49a2998fff971b6b1b64 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Shipping/Address.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" ?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<mapping strict="0"> + <wrapper>order[shipping_address]</wrapper> + <fields> + <firstname /> + <lastname /> + <company /> + <street> + <selector>[name='order[shipping_address][street][0]']</selector> + </street> + <city /> + <country_id> + <input>select</input> + </country_id> + <region_id> + <input>select</input> + </region_id> + <postcode /> + <telephone /> + </fields> +</mapping> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Shipping/Method.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Shipping/Method.php index 3d9673e29805dee1383ac9b3354c4905886748e8..90a75f665cbf9f95eebe2dfa26d135082d3912f4 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Shipping/Method.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Shipping/Method.php @@ -28,6 +28,13 @@ class Method extends Block */ protected $shippingMethod = '//dt[contains(.,"%s")]/following-sibling::*//*[contains(text(), "%s")]'; + /** + * Wait element. + * + * @var string + */ + private $waitElement = '.loading-mask'; + /** * Select shipping method. * @@ -36,6 +43,7 @@ class Method extends Block */ public function selectShippingMethod(array $shippingMethod) { + $this->waitFormLoading(); if ($this->_rootElement->find($this->shippingMethodsLink)->isVisible()) { $this->_rootElement->find($this->shippingMethodsLink)->click(); } @@ -46,4 +54,19 @@ class Method extends Block ); $this->_rootElement->find($selector, Locator::SELECTOR_XPATH)->click(); } + + /** + * Wait for form loading. + * + * @return void + */ + private function waitFormLoading() + { + $this->_rootElement->click(); + $this->browser->waitUntil( + function () { + return $this->browser->find($this->waitElement)->isVisible() ? null : true; + } + ); + } } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.php index 1779ad437c76e4192fd8c9774fc5a6f0ab8ccafb..71575ffb16b858cd43353c02d82f2d496eac4a51 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.php @@ -10,12 +10,13 @@ use Magento\Sales\Test\Fixture\OrderInjectable; use Magento\Sales\Test\Page\Adminhtml\OrderIndex; use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; use Magento\Mtf\TestCase\Injectable; +use Magento\Mtf\TestStep\TestStepFactory; /** * Preconditions: - * 1. Enable payment method "Check/Money Order". - * 2. Enable shipping method one of "Flat Rate". - * 3. Create order + * 1. Enable payment method: "Check/Money Order/Bank Transfer/Cash on Delivery/Purchase Order/Zero Subtotal Checkout". + * 2. Enable shipping method one of "Flat Rate/Free Shipping". + * 3. Create order. * * Steps: * 1. Login to backend. @@ -48,20 +49,7 @@ class CancelCreatedOrderTest extends Injectable protected $salesOrderView; /** - * Enable "Check/Money Order" and "Flat Rate" in configuration. - * - * @return void - */ - public function __prepare() - { - $this->objectManager->create( - \Magento\Config\Test\TestStep\SetupConfigurationStep::class, - ['configData' => 'checkmo, flatrate', 'rollback' => true] - )->run(); - } - - /** - * Inject pages + * Inject pages. * * @param OrderIndex $orderIndex * @param SalesOrderView $salesOrderView @@ -77,11 +65,17 @@ class CancelCreatedOrderTest extends Injectable * Cancel created order. * * @param OrderInjectable $order + * @param TestStepFactory $stepFactory + * @param string $configData * @return array */ - public function test(OrderInjectable $order) + public function test(OrderInjectable $order, TestStepFactory $stepFactory, $configData) { // Preconditions + $stepFactory->create( + \Magento\Config\Test\TestStep\SetupConfigurationStep::class, + ['configData' => $configData] + )->run(); $order->persist(); // Steps diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml index bcacacc57589a88806a2bcad18912ab84760ec8f..b65b9a31f72f3d7ff7290afb4393edeaf73679bc 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml @@ -7,14 +7,49 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Sales\Test\TestCase\CancelCreatedOrderTest" summary="Cancel Created Order for Offline Payment Methods" ticketId="MAGETWO-28191"> - <variation name="CancelCreatedOrderTestVariation1"> - <data name="description" xsi:type="string">cancel order and check status on storefront</data> + <variation name="CancelCreatedOrderTestVariationWithCheckMoneyOrderPaymentMethod" summary="Cancel order with check/money order payment method and check status on storefront"> <data name="order/dataset" xsi:type="string">default</data> <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::default,catalogProductSimple::default</data> <data name="status" xsi:type="string">Canceled</data> + <data name="configData" xsi:type="string">checkmo</data> <constraint name="Magento\Sales\Test\Constraint\AssertOrderCancelSuccessMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGrid" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" /> </variation> + <variation name="CancelCreatedOrderTestVariationWithZeroSubtotalCheckout" summary="Cancel order with zero subtotal checkout payment method and check status on storefront"> + <data name="order/dataset" xsi:type="string">default</data> + <data name="order/data/payment_auth_expiration/method" xsi:type="string">free</data> + <data name="order/data/shipping_method" xsi:type="string">freeshipping_freeshipping</data> + <data name="order/data/coupon_code/dataset" xsi:type="string">active_sales_rule_with_fixed_price_discount_coupon</data> + <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="status" xsi:type="string">Canceled</data> + <data name="configData" xsi:type="string">zero_subtotal_checkout, freeshipping</data> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderCancelSuccessMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" /> + </variation> + <variation name="CancelCreatedOrderTestVariationWithBankTransferPaymentMethod" summary="Cancel order with bank transfer payment method and check status on storefront"> + <data name="order/dataset" xsi:type="string">default</data> + <data name="order/data/payment_auth_expiration/method" xsi:type="string">banktransfer</data> + <data name="status" xsi:type="string">Canceled</data> + <data name="configData" xsi:type="string">banktransfer</data> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderCancelSuccessMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" /> + </variation> + <variation name="CancelCreatedOrderTestVariationWithCashOnDeliveryPaymentMethod" summary="Cancel order with cash on delivery payment method and check status on storefront"> + <data name="order/dataset" xsi:type="string">default</data> + <data name="order/data/payment_auth_expiration/method" xsi:type="string">cashondelivery</data> + <data name="status" xsi:type="string">Canceled</data> + <data name="configData" xsi:type="string">cashondelivery</data> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderCancelSuccessMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" /> + </variation> + <variation name="CancelCreatedOrderTestVariationWithPurchaseOrderPaymentMethod" summary="Cancel order with purchase order payment method and check status on storefront"> + <data name="order/dataset" xsi:type="string">default</data> + <data name="order/data/payment_auth_expiration/method" xsi:type="string">purchaseorder</data> + <data name="status" xsi:type="string">Canceled</data> + <data name="configData" xsi:type="string">purchaseorder</data> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderCancelSuccessMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" /> + </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.php index ed00a414bd0e689cfdb15b75ccf5d795ca40c992..9d19d10f4d40c6c3e317a97e7e83cd3c79e6f8ae 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.php @@ -10,10 +10,11 @@ use Magento\Sales\Test\Fixture\OrderInjectable; use Magento\Mtf\Fixture\FixtureFactory; use Magento\Mtf\Fixture\FixtureInterface; use Magento\Mtf\TestCase\Injectable; +use Magento\Mtf\TestStep\TestStepFactory; /** * Preconditions: - * 1. Enable payment method "Check/Money Order". + * 1. Enable payment method one of "Check/Money Order/Bank Transfer/Cash on Delivery/Purchase Order". * 2. Enable shipping method one of "Flat Rate/Free Shipping". * 3. Create order. * 4. Create Invoice. @@ -54,38 +55,34 @@ class CreateCreditMemoEntityTest extends Injectable 'price', ]; - /** - * Set up configuration. - * - * @param FixtureFactory $fixtureFactory - * @return void - */ - public function __prepare(FixtureFactory $fixtureFactory) - { - $this->fixtureFactory = $fixtureFactory; - - $setupConfigurationStep = $this->objectManager->create( - \Magento\Config\Test\TestStep\SetupConfigurationStep::class, - ['configData' => 'checkmo, flatrate'] - ); - $setupConfigurationStep->run(); - } - /** * Create credit memo. * + * @param TestStepFactory $stepFactory + * @param FixtureFactory $fixtureFactory * @param OrderInjectable $order * @param array $data + * @param string $configData * @return array */ - public function test(OrderInjectable $order, array $data) - { + public function test( + TestStepFactory $stepFactory, + FixtureFactory $fixtureFactory, + OrderInjectable $order, + array $data, + $configData + ) { // Preconditions + $this->fixtureFactory = $fixtureFactory; + $stepFactory->create( + \Magento\Config\Test\TestStep\SetupConfigurationStep::class, + ['configData' => $configData] + )->run(); $order->persist(); - $this->objectManager->create(\Magento\Sales\Test\TestStep\CreateInvoiceStep::class, ['order' => $order])->run(); + $stepFactory->create(\Magento\Sales\Test\TestStep\CreateInvoiceStep::class, ['order' => $order])->run(); // Steps - $createCreditMemoStep = $this->objectManager->create( + $createCreditMemoStep = $stepFactory->create( \Magento\Sales\Test\TestStep\CreateCreditMemoStep::class, ['order' => $order, 'data' => $data] ); diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.xml index 80e1bfdf81e8f39b5547fd96def138063fa00231..02b9640acbea4159c0560e8a4727a13cc36e1199 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.xml @@ -7,14 +7,14 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Sales\Test\TestCase\CreateCreditMemoEntityTest" summary="Create Credit Memo for Offline Payment Methods" ticketId="MAGETWO-29116"> - <variation name="CreateCreditMemoEntityTestVariation1"> - <data name="description" xsi:type="string">Assert items return to stock (partial refund)</data> + <variation name="CreateCreditMemoEntityTestVariation1" summary="Assert items return to stock (partial refund)"> <data name="data/items_data/0/back_to_stock" xsi:type="string">Yes</data> <data name="data/items_data/0/qty" xsi:type="string">1</data> <data name="data/form_data/send_email" xsi:type="string">Yes</data> <data name="order/dataset" xsi:type="string">default</data> <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::product_100_dollar</data> <data name="order/data/price/dataset" xsi:type="string">partial_refund</data> + <data name="configData" xsi:type="string">checkmo</data> <constraint name="Magento\Sales\Test\Constraint\AssertRefundSuccessCreateMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertCreditMemoButton" /> <constraint name="Magento\Sales\Test\Constraint\AssertRefundInCreditMemoTab" /> @@ -25,15 +25,15 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductForm" /> <constraint name="Magento\Sales\Test\Constraint\AssertCreditMemoItems" /> </variation> - <variation name="CreateCreditMemoEntityTestVariation2"> - <data name="description" xsi:type="string">Assert 0 shipping refund</data> + <variation name="CreateCreditMemoEntityTestVariation2" summary="Assert 0 shipping refund"> <data name="data/items_data/0/qty" xsi:type="string">1</data> <data name="data/form_data/shipping_amount" xsi:type="string">0</data> <data name="data/form_data/adjustment_positive" xsi:type="string">5</data> <data name="data/form_data/adjustment_negative" xsi:type="string">10</data> <data name="order/dataset" xsi:type="string">default</data> - <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::default</data> + <data name="order/data/payment_auth_expiration/method" xsi:type="string">banktransfer</data> <data name="order/data/price/dataset" xsi:type="string">full_refund_with_zero_shipping_refund</data> + <data name="configData" xsi:type="string">banktransfer</data> <constraint name="Magento\Sales\Test\Constraint\AssertRefundSuccessCreateMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertCreditMemoButton" /> <constraint name="Magento\Sales\Test\Constraint\AssertRefundInCreditMemoTab" /> @@ -41,5 +41,29 @@ <constraint name="Magento\Sales\Test\Constraint\AssertRefundedGrandTotalOnFrontend" /> <constraint name="Magento\Sales\Test\Constraint\AssertCreditMemoItems" /> </variation> + <variation name="CreateCreditMemoEntityTestVariationWithCashOnDeliveryPaymentMethod" summary="Assert 0 shipping refund with Cash on delivery payment method"> + <data name="data/items_data/0/qty" xsi:type="string">1</data> + <data name="data/form_data/shipping_amount" xsi:type="string">0</data> + <data name="data/form_data/adjustment_positive" xsi:type="string">5</data> + <data name="data/form_data/adjustment_negative" xsi:type="string">10</data> + <data name="order/dataset" xsi:type="string">default</data> + <data name="order/data/payment_auth_expiration/method" xsi:type="string">cashondelivery</data> + <data name="order/data/price/dataset" xsi:type="string">full_refund_with_zero_shipping_refund</data> + <data name="configData" xsi:type="string">cashondelivery</data> + <constraint name="Magento\Sales\Test\Constraint\AssertRefundSuccessCreateMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertRefundedGrandTotalOnFrontend" /> + </variation> + <variation name="CreateCreditMemoEntityTestVariationWithPurchaseOrderPaymentMethod" summary="Assert 0 shipping refund with Purchase Order payment method"> + <data name="data/items_data/0/qty" xsi:type="string">1</data> + <data name="data/form_data/shipping_amount" xsi:type="string">0</data> + <data name="data/form_data/adjustment_positive" xsi:type="string">5</data> + <data name="data/form_data/adjustment_negative" xsi:type="string">10</data> + <data name="order/dataset" xsi:type="string">default</data> + <data name="order/data/payment_auth_expiration/method" xsi:type="string">purchaseorder</data> + <data name="order/data/price/dataset" xsi:type="string">full_refund_with_zero_shipping_refund</data> + <data name="configData" xsi:type="string">purchaseorder</data> + <constraint name="Magento\Sales\Test\Constraint\AssertRefundSuccessCreateMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertRefundedGrandTotalOnFrontend" /> + </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateInvoiceEntityTest.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateInvoiceEntityTest.php index f62583583c3dc565579196d24ed564a14613eef9..f7cdaf74ab0f57e0544a392f6a936498bcb8efee 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateInvoiceEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateInvoiceEntityTest.php @@ -8,10 +8,11 @@ namespace Magento\Sales\Test\TestCase; use Magento\Sales\Test\Fixture\OrderInjectable; use Magento\Mtf\TestCase\Injectable; +use Magento\Mtf\TestStep\TestStepFactory; /** * Preconditions: - * 1. Enable payment method "Check/Money Order". + * 1. Enable payment method: "Check/Money Order/Bank Transfer/Cash on Delivery/Purchase Order/Zero Subtotal Checkout". * 2. Enable shipping method one of "Flat Rate/Free Shipping". * 3. Create order. * @@ -33,16 +34,21 @@ class CreateInvoiceEntityTest extends Injectable /* end tags */ /** - * Set up configuration. + * Factory for Test Steps. * + * @var TestStepFactory + */ + protected $stepFactory; + + /** + * Prepare data. + * + * @param TestStepFactory $stepFactory * @return void */ - public function __prepare() + public function __prepare(TestStepFactory $stepFactory) { - $this->objectManager->create( - \Magento\Config\Test\TestStep\SetupConfigurationStep::class, - ['configData' => 'checkmo, flatrate'] - )->run(); + $this->stepFactory = $stepFactory; } /** @@ -50,15 +56,20 @@ class CreateInvoiceEntityTest extends Injectable * * @param OrderInjectable $order * @param array $data + * @param string $configData * @return array */ - public function test(OrderInjectable $order, array $data) + public function test(OrderInjectable $order, array $data, $configData) { // Preconditions + $this->stepFactory->create( + \Magento\Config\Test\TestStep\SetupConfigurationStep::class, + ['configData' => $configData] + )->run(); $order->persist(); // Steps - $result = $this->objectManager->create( + $result = $this->stepFactory->create( \Magento\Sales\Test\TestStep\CreateInvoiceStep::class, ['order' => $order, 'data' => $data] )->run(); @@ -73,6 +84,6 @@ class CreateInvoiceEntityTest extends Injectable */ public function tearDown() { - $this->objectManager->create(\Magento\Customer\Test\TestStep\LogoutCustomerOnFrontendStep::class)->run(); + $this->stepFactory->create(\Magento\Customer\Test\TestStep\LogoutCustomerOnFrontendStep::class)->run(); } } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateInvoiceEntityTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateInvoiceEntityTest.xml index afc4bad5e706db538cd5957201a4a5c9347a3605..8753de91d1f4301710f15a968b7a7ea24e04d663 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateInvoiceEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateInvoiceEntityTest.xml @@ -10,11 +10,11 @@ <variation name="CreateInvoiceEntityTestVariation1"> <data name="order/dataset" xsi:type="string">default</data> <data name="order/data/price/dataset" xsi:type="string">full_invoice</data> - <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::default</data> <data name="order/data/total_qty_ordered/0" xsi:type="string">1</data> <data name="data/items_data/0/qty" xsi:type="string">-</data> <data name="data/form_data/do_shipment" xsi:type="string">Yes</data> <data name="data/form_data/comment_text" xsi:type="string">comments</data> + <data name="configData" xsi:type="string">checkmo</data> <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceWithShipmentSuccessMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertNoInvoiceButton" /> <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceInInvoicesTab" /> @@ -29,14 +29,57 @@ <data name="order/data/price/dataset" xsi:type="string">partial_invoice</data> <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::product_100_dollar</data> <data name="order/data/total_qty_ordered/0" xsi:type="string">-</data> + <data name="order/data/payment_auth_expiration/method" xsi:type="string">banktransfer</data> <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="configData" xsi:type="string">banktransfer</data> <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceSuccessCreateMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceInInvoicesTab" /> <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceInInvoicesGrid" /> <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceItems" /> <constraint name="Magento\Sales\Test\Constraint\AssertInvoicedAmountOnFrontend" /> </variation> + <variation name="CreateInvoiceEntityTestVariationWithCashOnDeliveryPaymentMethod"> + <data name="order/dataset" xsi:type="string">default</data> + <data name="order/data/price/dataset" xsi:type="string">partial_invoice</data> + <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::product_100_dollar</data> + <data name="order/data/total_qty_ordered/0" xsi:type="string">-</data> + <data name="order/data/payment_auth_expiration/method" xsi:type="string">cashondelivery</data> + <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="configData" xsi:type="string">cashondelivery</data> + <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceSuccessCreateMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertInvoicedAmountOnFrontend" /> + </variation> + <variation name="CreateInvoiceEntityTestVariationWithPurchaseOrderPaymentMethod"> + <data name="order/dataset" xsi:type="string">default</data> + <data name="order/data/price/dataset" xsi:type="string">partial_invoice</data> + <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::product_100_dollar</data> + <data name="order/data/total_qty_ordered/0" xsi:type="string">-</data> + <data name="order/data/payment_auth_expiration/method" xsi:type="string">purchaseorder</data> + <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="configData" xsi:type="string">purchaseorder</data> + <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceSuccessCreateMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertInvoicedAmountOnFrontend" /> + </variation> + <variation name="CreateInvoiceEntityTestVariationWithZeroSubtotalCheckout"> + <data name="order/dataset" xsi:type="string">default</data> + <data name="order/data/price/dataset" xsi:type="string">partial_invoice</data> + <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="order/data/total_qty_ordered/0" xsi:type="string">-</data> + <data name="order/data/payment_auth_expiration/method" xsi:type="string">free</data> + <data name="order/data/shipping_method" xsi:type="string">freeshipping_freeshipping</data> + <data name="order/data/coupon_code/dataset" xsi:type="string">active_sales_rule_with_fixed_price_discount_coupon</data> + <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="configData" xsi:type="string">zero_subtotal_checkout, freeshipping</data> + <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceSuccessCreateMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertInvoicedAmountOnFrontend" /> + </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/FillBillingAddressStep.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/FillBillingAddressStep.php index bde5bff6de9d4e1f53969137ac86c94d8323c7fd..f6d0c8325bfc38500c4cd5a5d7289e8b3416439a 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/FillBillingAddressStep.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/FillBillingAddressStep.php @@ -11,7 +11,7 @@ use Magento\Sales\Test\Page\Adminhtml\OrderCreateIndex; use Magento\Mtf\TestStep\TestStepInterface; /** - * Fill Sales Data. + * Fill Billing Address. */ class FillBillingAddressStep implements TestStepInterface { @@ -23,7 +23,7 @@ class FillBillingAddressStep implements TestStepInterface protected $orderCreateIndex; /** - * Address. + * Billing Address fixture. * * @var Address */ @@ -37,14 +37,13 @@ class FillBillingAddressStep implements TestStepInterface protected $saveAddress; /** - * Flag for set same as billing shipping address. + * Flag to set 'Same as billing address' for shipping address. * * @var string */ protected $setShippingAddress; /** - * @constructor * @param OrderCreateIndex $orderCreateIndex * @param Address $billingAddress * @param string $saveAddress @@ -63,14 +62,14 @@ class FillBillingAddressStep implements TestStepInterface } /** - * Fill Sales Data. + * Fill Billing Address. * - * @return Address + * @return array */ public function run() { $this->orderCreateIndex->getCreateBlock() - ->fillAddresses($this->billingAddress, $this->saveAddress, $this->setShippingAddress); + ->fillBillingAddress($this->billingAddress, $this->saveAddress, $this->setShippingAddress); return ['billingAddress' => $this->billingAddress]; } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/FillShippingAddressStep.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/FillShippingAddressStep.php new file mode 100644 index 0000000000000000000000000000000000000000..8ff05dfca95bb016b4b72e5db07f5fa2ffb139ca --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/FillShippingAddressStep.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\TestStep; + +use Magento\Customer\Test\Fixture\Address; +use Magento\Sales\Test\Page\Adminhtml\OrderCreateIndex; +use Magento\Mtf\TestStep\TestStepInterface; + +/** + * Fill Shipping Address. + */ +class FillShippingAddressStep implements TestStepInterface +{ + /** + * Sales order create index page. + * + * @var OrderCreateIndex + */ + protected $orderCreateIndex; + + /** + * Shipping Address fixture. + * + * @var Address + */ + protected $shippingAddress; + + /** + * @param OrderCreateIndex $orderCreateIndex + * @param Address $shippingAddress [optional] + */ + public function __construct( + OrderCreateIndex $orderCreateIndex, + Address $shippingAddress = null + ) { + $this->orderCreateIndex = $orderCreateIndex; + $this->shippingAddress = $shippingAddress; + } + + /** + * Fill Shipping Address. + * + * @return void + */ + public function run() + { + $this->orderCreateIndex->getCreateBlock()->fillShippingAddress($this->shippingAddress); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml index c48430b00e7ea4412265dfaf4d91ed85cbd2819c..ec2da3f2607b2dda7e4b375e11192f9844d839fd 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml @@ -28,7 +28,8 @@ <step name="addProducts" module="Magento_Sales" next="updateProductsData" /> <step name="updateProductsData" module="Magento_Sales" next="fillAccountInformation" /> <step name="fillAccountInformation" module="Magento_Sales" next="fillBillingAddress" /> - <step name="fillBillingAddress" module="Magento_Sales" next="selectShippingMethodForOrder" /> + <step name="fillBillingAddress" module="Magento_Sales" next="fillShippingAddress" /> + <step name="fillShippingAddress" module="Magento_Sales" next="selectShippingMethodForOrder" /> <step name="selectShippingMethodForOrder" module="Magento_Sales" next="selectPaymentMethodForOrder" /> <step name="selectPaymentMethodForOrder" module="Magento_Sales" next="submitOrder" /> <step name="submitOrder" module="Magento_Sales" /> diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/AbstractFormContainers.php b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/AbstractFormContainers.php index b6ed37af715be90fc600aa5728744ccd3a160d68..180afa8fe7ec6b3a862ef9f80e077fcca70b354e 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/AbstractFormContainers.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/AbstractFormContainers.php @@ -158,7 +158,7 @@ abstract class AbstractFormContainers extends Form /** * Fill specified form with containers data. - * + * * Input data in format * [[container => [field => [attribute_name => attribute_value, ..], ..], ..] * where container name can be empty if a field is not assigned to any container. diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php index 3fc6f044f88521794f579aa653bacd6d87e44d14..80df7e6f8c631722fb314525b2d6733e2ac605ad 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php @@ -142,7 +142,7 @@ class DataGrid extends Grid * * @var string */ - protected $currentPage = '[data-ui-id="current-page-input"]'; + protected $currentPage = ".//*[@data-ui-id='current-page-input'][not(ancestor::*[@class='sticky-header'])]"; /** * Clear all applied Filters. @@ -347,7 +347,7 @@ class DataGrid extends Grid $this->sortGridByField('ID'); } foreach ($items as $item) { - $this->_rootElement->find($this->currentPage)->setValue(''); + $this->_rootElement->find($this->currentPage, Locator::SELECTOR_XPATH)->setValue(''); $this->waitLoader(); $selectItem = $this->getRow($item)->find($this->selectItem); do { diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/CreateHandlerTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/CreateHandlerTest.php index 992c3bf310f51995ece1b78f6c566fd1d3baf1a4..2c42a289bd4c017a15591d9a110220fce74de346 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/CreateHandlerTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/CreateHandlerTest.php @@ -18,6 +18,10 @@ class CreateHandlerTest extends \PHPUnit_Framework_TestCase */ protected $createHandler; + private $fileName = '/m/a/magento_image.jpg'; + + private $fileLabel = 'Magento image'; + protected function setUp() { $this->createHandler = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( @@ -28,10 +32,8 @@ class CreateHandlerTest extends \PHPUnit_Framework_TestCase /** * @covers \Magento\Catalog\Model\Product\Gallery\CreateHandler::execute */ - public function testExecute() + public function testExecuteWithImageDuplicate() { - $fileName = '/m/a/magento_image.jpg'; - $fileLabel = 'Magento image'; /** @var $product \Magento\Catalog\Model\Product */ $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( \Magento\Catalog\Model\Product::class @@ -39,20 +41,141 @@ class CreateHandlerTest extends \PHPUnit_Framework_TestCase $product->load(1); $product->setData( 'media_gallery', - ['images' => ['image' => ['file' => $fileName, 'label' => $fileLabel]]] + ['images' => ['image' => ['file' => $this->fileName, 'label' => $this->fileLabel]]] ); - $product->setData('image', $fileName); + $product->setData('image', $this->fileName); $this->createHandler->execute($product); $this->assertStringStartsWith('/m/a/magento_image', $product->getData('media_gallery/images/image/new_file')); - $this->assertEquals($fileLabel, $product->getData('image_label')); + $this->assertEquals($this->fileLabel, $product->getData('image_label')); $product->setIsDuplicate(true); $product->setData( 'media_gallery', - ['images' => ['image' => ['value_id' => '100', 'file' => $fileName, 'label' => $fileLabel]]] + ['images' => ['image' => ['value_id' => '100', 'file' => $this->fileName, 'label' => $this->fileLabel]]] ); $this->createHandler->execute($product); $this->assertStringStartsWith('/m/a/magento_image', $product->getData('media_gallery/duplicate/100')); - $this->assertEquals($fileLabel, $product->getData('image_label')); + $this->assertEquals($this->fileLabel, $product->getData('image_label')); + } + + /** + * @dataProvider executeDataProvider + * @param $image + * @param $smallImage + * @param $swatchImage + * @param $thumbnail + */ + public function testExecuteWithImageRoles($image, $smallImage, $swatchImage, $thumbnail) + { + /** @var $product \Magento\Catalog\Model\Product */ + $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Model\Product::class + ); + $product->load(1); + $product->setData( + 'media_gallery', + ['images' => ['image' => ['file' => $this->fileName, 'label' => '']]] + ); + $product->setData('image', $image); + $product->setData('small_image', $smallImage); + $product->setData('swatch_image', $swatchImage); + $product->setData('thumbnail', $thumbnail); + $this->createHandler->execute($product); + + $resource = $product->getResource(); + $id = $product->getId(); + $storeId = $product->getStoreId(); + + $this->assertStringStartsWith('/m/a/magento_image', $product->getData('media_gallery/images/image/new_file')); + $this->assertEquals( + $image, + $resource->getAttributeRawValue($id, $resource->getAttribute('image'), $storeId) + ); + $this->assertEquals( + $smallImage, + $resource->getAttributeRawValue($id, $resource->getAttribute('small_image'), $storeId) + ); + $this->assertEquals( + $swatchImage, + $resource->getAttributeRawValue($id, $resource->getAttribute('swatch_image'), $storeId) + ); + $this->assertEquals( + $thumbnail, + $resource->getAttributeRawValue($id, $resource->getAttribute('thumbnail'), $storeId) + ); + } + + /** + * @dataProvider executeDataProvider + * @param $image + * @param $smallImage + * @param $swatchImage + * @param $thumbnail + */ + public function testExecuteWithoutImages($image, $smallImage, $swatchImage, $thumbnail) + { + /** @var $product \Magento\Catalog\Model\Product */ + $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Model\Product::class + ); + $product->load(1); + $product->setData( + 'media_gallery', + ['images' => ['image' => ['file' => $this->fileName, 'label' => '']]] + ); + $product->setData('image', $image); + $product->setData('small_image', $smallImage); + $product->setData('swatch_image', $swatchImage); + $product->setData('thumbnail', $thumbnail); + $this->createHandler->execute($product); + + $product->unsetData('image'); + $product->unsetData('small_image'); + $product->unsetData('swatch_image'); + $product->unsetData('thumbnail'); + $this->createHandler->execute($product); + + $resource = $product->getResource(); + $id = $product->getId(); + $storeId = $product->getStoreId(); + + $this->assertStringStartsWith('/m/a/magento_image', $product->getData('media_gallery/images/image/new_file')); + $this->assertEquals( + $image, + $resource->getAttributeRawValue($id, $resource->getAttribute('image'), $storeId) + ); + $this->assertEquals( + $smallImage, + $resource->getAttributeRawValue($id, $resource->getAttribute('small_image'), $storeId) + ); + $this->assertEquals( + $swatchImage, + $resource->getAttributeRawValue($id, $resource->getAttribute('swatch_image'), $storeId) + ); + $this->assertEquals( + $thumbnail, + $resource->getAttributeRawValue($id, $resource->getAttribute('thumbnail'), $storeId) + ); + } + + /** + * @return array + */ + public function executeDataProvider() + { + return [ + [ + 'image' => $this->fileName, + 'small_image' => $this->fileName, + 'swatch_image' => $this->fileName, + 'thumbnail' => $this->fileName + ], + [ + 'image' => 'no_selection', + 'small_image' => 'no_selection', + 'swatch_image' => 'no_selection', + 'thumbnail' => 'no_selection' + ] + ]; } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple.php index aadf1e74a883ce823d574178cba29ca617f5abf0..3125cc2a690ba9a0788079f37be339e5e6b5c28f 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple.php @@ -160,14 +160,14 @@ $oldOptions = [ 'sort_order' => 0, 'values' => [ [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 1', 'price' => 3, 'price_type' => 'fixed', 'sku' => '3-1-select', ], [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 2', 'price' => 3, 'price_type' => 'fixed', @@ -183,14 +183,14 @@ $oldOptions = [ 'sort_order' => 0, 'values' => [ [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 1', 'price' => 3, 'price_type' => 'fixed', 'sku' => '4-1-radio', ], [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 2', 'price' => 3, 'price_type' => 'fixed', diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_admin_store.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_admin_store.php index 18c70968039f8f6df0056daa98da1dbef068e055..d933cd00656d3c8ffde5bd37526aa31aaacba681 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_admin_store.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_admin_store.php @@ -98,14 +98,14 @@ $oldOptions = [ 'sort_order' => 0, 'values' => [ [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 1', 'price' => 3, 'price_type' => 'fixed', 'sku' => '3-1-select', ], [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 2', 'price' => 3, 'price_type' => 'fixed', @@ -121,14 +121,14 @@ $oldOptions = [ 'sort_order' => 0, 'values' => [ [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 1', 'price' => 3, 'price_type' => 'fixed', 'sku' => '4-1-radio', ], [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 2', 'price' => 3, 'price_type' => 'fixed', diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options.php index 0366e90cd9772036315678f6e3b10d1f59b615fb..a0a29753bfeed384aa1a4131e4ca2fed26491e95 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options.php @@ -49,14 +49,14 @@ $oldOptions = [ 'sort_order' => 0, 'values' => [ [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 1', 'price' => '3,000.00', 'price_type' => 'fixed', 'sku' => '3-1-select', ], [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 2', 'price' => '5,000.00', 'price_type' => 'fixed', @@ -72,14 +72,14 @@ $oldOptions = [ 'sort_order' => 0, 'values' => [ [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 1', 'price' => '600.234', 'price_type' => 'fixed', 'sku' => '4-1-radio', ], [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 2', 'price' => '40,000.00', 'price_type' => 'fixed', 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 9f3d16a998987d600e1f702f4a4228e1ff06c9b7..43ac499b8bd9dfce4312896c97ab506a4c93f02d 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -20,6 +20,7 @@ use Magento\Catalog\Model\Category; use Magento\Framework\App\Bootstrap; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\ImportExport\Model\Import; +use Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface; /** * Class ProductTest @@ -1050,9 +1051,9 @@ class ProductTest extends \Magento\TestFramework\Indexer\TestCase * @magentoAppIsolation enabled * @dataProvider validateUrlKeysDataProvider * @param $importFile string - * @param $errorsCount int + * @param $expectedErrors array */ - public function testValidateUrlKeys($importFile, $errorsCount) + public function testValidateUrlKeys($importFile, $expectedErrors) { $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( \Magento\Framework\Filesystem::class @@ -1066,19 +1067,16 @@ class ProductTest extends \Magento\TestFramework\Indexer\TestCase 'directory' => $directory ] ); + /** @var \Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface $errors */ $errors = $this->_model->setParameters( ['behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, 'entity' => 'catalog_product'] )->setSource( $source )->validateData(); - - $this->assertTrue($errors->getErrorsCount() == $errorsCount); - if ($errorsCount >= 1) { - $this->assertEquals( - "Specified URL key already exists", - $errors->getErrorByRowNumber(1)[0]->getErrorMessage() - ); - } + $this->assertEquals( + $expectedErrors[RowValidatorInterface::ERROR_DUPLICATE_URL_KEY], + count($errors->getErrorsByCode([RowValidatorInterface::ERROR_DUPLICATE_URL_KEY])) + ); } /** @@ -1087,9 +1085,24 @@ class ProductTest extends \Magento\TestFramework\Indexer\TestCase public function validateUrlKeysDataProvider() { return [ - ['products_to_check_valid_url_keys.csv', 0], - ['products_to_check_duplicated_url_keys.csv', 2], - ['products_to_check_duplicated_names.csv' , 1] + [ + 'products_to_check_valid_url_keys.csv', + [ + RowValidatorInterface::ERROR_DUPLICATE_URL_KEY => 0 + ] + ], + [ + 'products_to_check_duplicated_url_keys.csv', + [ + RowValidatorInterface::ERROR_DUPLICATE_URL_KEY => 2 + ] + ], + [ + 'products_to_check_duplicated_names.csv' , + [ + RowValidatorInterface::ERROR_DUPLICATE_URL_KEY => 1 + ] + ] ]; } diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php index a3bf1686b5fdb2181f28939a1bc10d36170532ea..ffee568b0622fa8ef3f5af185e24805367ee9203 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php @@ -18,16 +18,30 @@ $productModel = $objectManager->create(\Magento\Catalog\Model\Product::class); $customOptions = [ [ - 'id' => 'test_option_code_1', - 'option_id' => '0', + 'option_id' => null, 'sort_order' => '0', 'title' => 'Option 1', 'type' => 'drop_down', 'is_require' => 1, 'values' => [ - 1 => ['option_type_id' => -1, 'title' => 'Option 1 & Value 1"', 'price' => '1.00', 'price_type' => 'fixed'], - 2 => ['option_type_id' => -1, 'title' => 'Option 1 & Value 2"', 'price' => '2.00', 'price_type' => 'fixed'], - 3 => ['option_type_id' => -1, 'title' => 'Option 1 & Value 3"', 'price' => '3.00', 'price_type' => 'fixed'] + 1 => [ + 'option_type_id' => null, + 'title' => 'Option 1 & Value 1"', + 'price' => '1.00', + 'price_type' => 'fixed' + ], + 2 => [ + 'option_type_id' => null, + 'title' => 'Option 1 & Value 2"', + 'price' => '2.00', + 'price_type' => 'fixed' + ], + 3 => [ + 'option_type_id' => null, + 'title' => 'Option 1 & Value 3"', + 'price' => '3.00', + 'price_type' => 'fixed' + ] ] ], [ diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/Configurable/PriceTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/Configurable/PriceTest.php index 053e33da09fe9f812aa7a1d4164cf274467a3a6c..6322a60cef8a5fda1b50e220b10de7c5385956d4 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/Configurable/PriceTest.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/Configurable/PriceTest.php @@ -90,8 +90,7 @@ class PriceTest extends \PHPUnit_Framework_TestCase $options = $this->prepareOptions( [ [ - 'id' => 1, - 'option_id' => 0, + 'option_id' => null, 'previous_group' => 'text', 'title' => 'Test Field', 'type' => 'field', diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php index b35d87d48063a39011a92e5184090402ea64b4c0..ff08056e4b18def3f520d2a5d9f2090b168d5ec8 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php @@ -104,14 +104,14 @@ $oldOptions = [ 'sort_order' => 0, 'values' => [ [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 1', 'price' => 3, 'price_type' => 'fixed', 'sku' => '3-1-select', ], [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 2', 'price' => 3, 'price_type' => 'fixed', @@ -127,14 +127,14 @@ $oldOptions = [ 'sort_order' => 0, 'values' => [ [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 1', 'price' => 3, 'price_type' => 'fixed', 'sku' => '4-1-radio', ], [ - 'option_type_id' => -1, + 'option_type_id' => null, 'title' => 'Option 2', 'price' => 3, 'price_type' => 'fixed',