diff --git a/.gitignore b/.gitignore index 9269cefc51fa0178e49324a776bef8b575d7ac08..a5b85031db205be7a5ccdf34fbfb4ead11787617 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,8 @@ atlassian* /lib/internal/flex/varien/.settings /node_modules /.grunt +/Gruntfile.js +/package.json /pub/media/*.* !/pub/media/.htaccess diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Stock.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Stock.php index 5c3fd4730aaed4907cbf197f6a5298060ad12acf..0bb468b77ee6ea18df11e7fd349e8315c6f74318 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Stock.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Stock.php @@ -59,7 +59,7 @@ class Stock extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend if (isset($stockData['qty']) && $stockData['qty'] === '') { $stockData['qty'] = null; } - if ($object->getStockData() !== null || $stockData !== null) { + if ($object->getStockData() !== null && $stockData !== null) { $object->setStockData(array_replace((array)$object->getStockData(), (array)$stockData)); } $object->unsetData($this->getAttribute()->getAttributeCode()); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/BaseSelectProcessorInterface.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/BaseSelectProcessorInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..e6a995b654703402175f79ccc6e50b5172db5fd4 --- /dev/null +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/BaseSelectProcessorInterface.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Model\ResourceModel\Product; + +use Magento\Framework\DB\Select; + +/** + * Interface BaseSelectProcessorInterface + * @api + */ +interface BaseSelectProcessorInterface +{ + /** + * Product table alias + */ + const PRODUCT_TABLE_ALIAS = 'child'; + + /** + * @param Select $select + * @return Select + */ + public function process(Select $select); +} diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/CompositeBaseSelectProcessor.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/CompositeBaseSelectProcessor.php new file mode 100644 index 0000000000000000000000000000000000000000..86f5a23708400ef40a58677f07e57552a39bd6bd --- /dev/null +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/CompositeBaseSelectProcessor.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Model\ResourceModel\Product; + +use Magento\Framework\DB\Select; +use Magento\Framework\Exception\InputException; + +/** + * Class CompositeBaseSelectProcessor + */ +class CompositeBaseSelectProcessor implements BaseSelectProcessorInterface +{ + /** + * @var BaseSelectProcessorInterface[] + */ + private $baseSelectProcessors; + + /** + * @param BaseSelectProcessorInterface[] $baseSelectProcessors + * @throws InputException + */ + public function __construct( + array $baseSelectProcessors + ) { + foreach ($baseSelectProcessors as $baseSelectProcessor) { + if (!$baseSelectProcessor instanceof BaseSelectProcessorInterface) { + throw new InputException( + __('Processor %1 doesn\'t implement BaseSelectProcessorInterface', get_class($baseSelectProcessor)) + ); + } + } + $this->baseSelectProcessors = $baseSelectProcessors; + } + + /** + * @param Select $select + * @return Select + */ + public function process(Select $select) + { + foreach ($this->baseSelectProcessors as $baseSelectProcessor) { + $select = $baseSelectProcessor->process($select); + } + return $select; + } +} diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/LinkedProductSelectBuilderByIndexPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/LinkedProductSelectBuilderByIndexPrice.php index ea72691ea003939fc277299bee214da316f4f757..3aa6642c82d845eb6ca1143f9c82484c53c659f9 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/LinkedProductSelectBuilderByIndexPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/LinkedProductSelectBuilderByIndexPrice.php @@ -6,7 +6,8 @@ namespace Magento\Catalog\Model\ResourceModel\Product\Indexer; use Magento\Catalog\Api\Data\ProductInterface; -use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\Select; use Magento\Catalog\Model\ResourceModel\Product\LinkedProductSelectBuilderInterface; @@ -32,22 +33,31 @@ class LinkedProductSelectBuilderByIndexPrice implements LinkedProductSelectBuild */ private $metadataPool; + /** + * @var BaseSelectProcessorInterface + */ + private $baseSelectProcessor; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\ResourceConnection $resourceConnection * @param \Magento\Customer\Model\Session $customerSession * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool + * @param BaseSelectProcessorInterface $baseSelectProcessor */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\App\ResourceConnection $resourceConnection, \Magento\Customer\Model\Session $customerSession, - \Magento\Framework\EntityManager\MetadataPool $metadataPool + \Magento\Framework\EntityManager\MetadataPool $metadataPool, + BaseSelectProcessorInterface $baseSelectProcessor = null ) { $this->storeManager = $storeManager; $this->resource = $resourceConnection; $this->customerSession = $customerSession; $this->metadataPool = $metadataPool; + $this->baseSelectProcessor = (null !== $baseSelectProcessor) + ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); } /** @@ -58,24 +68,27 @@ class LinkedProductSelectBuilderByIndexPrice implements LinkedProductSelectBuild $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); $productTable = $this->resource->getTableName('catalog_product_entity'); - return [$this->resource->getConnection()->select() + $priceSelect = $this->resource->getConnection()->select() ->from(['parent' => $productTable], '') ->joinInner( ['link' => $this->resource->getTableName('catalog_product_relation')], "link.parent_id = parent.$linkField", [] )->joinInner( - ['child' => $productTable], - "child.entity_id = link.child_id", + [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], + sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), ['entity_id'] )->joinInner( ['t' => $this->resource->getTableName('catalog_product_index_price')], - 't.entity_id = child.entity_id', + sprintf('t.entity_id = %s.entity_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), [] - )->where('parent.entity_id = ? ', $productId) + )->where('parent.entity_id = ?', $productId) ->where('t.website_id = ?', $this->storeManager->getStore()->getWebsiteId()) ->where('t.customer_group_id = ?', $this->customerSession->getCustomerGroupId()) ->order('t.min_price ' . Select::SQL_ASC) - ->limit(1)]; + ->limit(1); + $priceSelect = $this->baseSelectProcessor->process($priceSelect); + + return [$priceSelect]; } } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByBasePrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByBasePrice.php index d325ab1a9a08d1175c0fedb2a94c10ac5d7dc3c2..7caa72b367979bc4ecbded5641490a59f7835928 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByBasePrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByBasePrice.php @@ -7,6 +7,7 @@ namespace Magento\Catalog\Model\ResourceModel\Product; use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Product; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\Select; use Magento\Store\Model\Store; @@ -37,25 +38,34 @@ class LinkedProductSelectBuilderByBasePrice implements LinkedProductSelectBuilde */ private $metadataPool; + /** + * @var BaseSelectProcessorInterface + */ + private $baseSelectProcessor; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\ResourceConnection $resourceConnection * @param \Magento\Eav\Model\Config $eavConfig * @param \Magento\Catalog\Helper\Data $catalogHelper * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool + * @param BaseSelectProcessorInterface $baseSelectProcessor */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\App\ResourceConnection $resourceConnection, \Magento\Eav\Model\Config $eavConfig, \Magento\Catalog\Helper\Data $catalogHelper, - \Magento\Framework\EntityManager\MetadataPool $metadataPool + \Magento\Framework\EntityManager\MetadataPool $metadataPool, + BaseSelectProcessorInterface $baseSelectProcessor = null ) { $this->storeManager = $storeManager; $this->resource = $resourceConnection; $this->eavConfig = $eavConfig; $this->catalogHelper = $catalogHelper; $this->metadataPool = $metadataPool; + $this->baseSelectProcessor = (null !== $baseSelectProcessor) + ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); } /** @@ -74,18 +84,19 @@ class LinkedProductSelectBuilderByBasePrice implements LinkedProductSelectBuilde "link.parent_id = parent.$linkField", [] )->joinInner( - ['child' => $productTable], - "child.entity_id = link.child_id", + [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], + sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), ['entity_id'] )->joinInner( ['t' => $priceAttribute->getBackendTable()], - "t.$linkField = child.$linkField", + sprintf('t.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), [] - )->where('parent.entity_id = ? ', $productId) + )->where('parent.entity_id = ?', $productId) ->where('t.attribute_id = ?', $priceAttribute->getAttributeId()) ->where('t.value IS NOT NULL') ->order('t.value ' . Select::SQL_ASC) ->limit(1); + $priceSelect = $this->baseSelectProcessor->process($priceSelect); $priceSelectDefault = clone $priceSelect; $priceSelectDefault->where('t.store_id = ?', Store::DEFAULT_STORE_ID); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php index 792a8f5b86d102204a93491c0413ae2839b16a73..68eaf206e293fea3e90c04e9dfb7bc0329704162 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php @@ -7,9 +7,13 @@ namespace Magento\Catalog\Model\ResourceModel\Product; use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Product; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\Select; use Magento\Store\Model\Store; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBuilderInterface { /** @@ -47,6 +51,11 @@ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBui */ private $metadataPool; + /** + * @var BaseSelectProcessorInterface + */ + private $baseSelectProcessor; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\ResourceConnection $resourceConnection @@ -55,6 +64,7 @@ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBui * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool + * @param BaseSelectProcessorInterface $baseSelectProcessor */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, @@ -63,7 +73,8 @@ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBui \Magento\Catalog\Helper\Data $catalogHelper, \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, - \Magento\Framework\EntityManager\MetadataPool $metadataPool + \Magento\Framework\EntityManager\MetadataPool $metadataPool, + BaseSelectProcessorInterface $baseSelectProcessor = null ) { $this->storeManager = $storeManager; $this->resource = $resourceConnection; @@ -72,6 +83,8 @@ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBui $this->dateTime = $dateTime; $this->localeDate = $localeDate; $this->metadataPool = $metadataPool; + $this->baseSelectProcessor = (null !== $baseSelectProcessor) + ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); } /** @@ -95,12 +108,12 @@ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBui "link.parent_id = parent.$linkField", [] )->joinInner( - ['child' => $productTable], - "child.entity_id = link.child_id", + [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], + sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), ['entity_id'] )->joinInner( ['t' => $specialPriceAttribute->getBackendTable()], - "t.$linkField = child.$linkField", + sprintf('t.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), [] )->joinLeft( ['special_from' => $specialPriceFromDate->getBackendTable()], @@ -116,7 +129,7 @@ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBui $specialPriceToDate->getAttributeId() ), '' - )->where('parent.entity_id = ? ', $productId) + )->where('parent.entity_id = ?', $productId) ->where('t.attribute_id = ?', $specialPriceAttribute->getAttributeId()) ->where('t.value IS NOT NULL') ->where( @@ -127,6 +140,7 @@ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBui $currentDate )->order('t.value ' . Select::SQL_ASC) ->limit(1); + $specialPrice = $this->baseSelectProcessor->process($specialPrice); $specialPriceDefault = clone $specialPrice; $specialPriceDefault->where('t.store_id = ?', Store::DEFAULT_STORE_ID); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php index d2d6d89c0a2a5828290e1191147451e4f6d20b7b..25bf83f837de72cec501379378e6960084d6b1fd 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php @@ -6,7 +6,7 @@ namespace Magento\Catalog\Model\ResourceModel\Product; use Magento\Catalog\Api\Data\ProductInterface; -use Magento\Catalog\Model\Product; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\Select; class LinkedProductSelectBuilderByTierPrice implements LinkedProductSelectBuilderInterface @@ -41,25 +41,34 @@ class LinkedProductSelectBuilderByTierPrice implements LinkedProductSelectBuilde */ private $metadataPool; + /** + * @var BaseSelectProcessorInterface + */ + private $baseSelectProcessor; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\ResourceConnection $resourceConnection * @param \Magento\Customer\Model\Session $customerSession * @param \Magento\Catalog\Helper\Data $catalogHelper * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool + * @param BaseSelectProcessorInterface $baseSelectProcessor */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\App\ResourceConnection $resourceConnection, \Magento\Customer\Model\Session $customerSession, \Magento\Catalog\Helper\Data $catalogHelper, - \Magento\Framework\EntityManager\MetadataPool $metadataPool + \Magento\Framework\EntityManager\MetadataPool $metadataPool, + BaseSelectProcessorInterface $baseSelectProcessor = null ) { $this->storeManager = $storeManager; $this->resource = $resourceConnection; $this->customerSession = $customerSession; $this->catalogHelper = $catalogHelper; $this->metadataPool = $metadataPool; + $this->baseSelectProcessor = (null !== $baseSelectProcessor) + ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); } /** @@ -77,18 +86,19 @@ class LinkedProductSelectBuilderByTierPrice implements LinkedProductSelectBuilde "link.parent_id = parent.$linkField", [] )->joinInner( - ['child' => $productTable], - "child.entity_id = link.child_id", + [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], + sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), ['entity_id'] )->joinInner( ['t' => $this->resource->getTableName('catalog_product_entity_tier_price')], - "t.$linkField = child.$linkField", + sprintf('t.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), [] - )->where('parent.entity_id = ? ', $productId) + )->where('parent.entity_id = ?', $productId) ->where('t.all_groups = 1 OR customer_group_id = ?', $this->customerSession->getCustomerGroupId()) ->where('t.qty = ?', 1) ->order('t.value ' . Select::SQL_ASC) ->limit(1); + $priceSelect = $this->baseSelectProcessor->process($priceSelect); $priceSelectDefault = clone $priceSelect; $priceSelectDefault->where('t.website_id = ?', self::DEFAULT_WEBSITE_ID); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/StatusBaseSelectProcessor.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/StatusBaseSelectProcessor.php new file mode 100644 index 0000000000000000000000000000000000000000..656998113fdb92e50e5177db4876651cfcd2023a --- /dev/null +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/StatusBaseSelectProcessor.php @@ -0,0 +1,61 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Model\ResourceModel\Product; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Eav\Model\Config; +use Magento\Framework\DB\Select; +use Magento\Framework\EntityManager\MetadataPool; + +/** + * Class StatusBaseSelectProcessor + */ +class StatusBaseSelectProcessor implements BaseSelectProcessorInterface +{ + /** + * @var Config + */ + private $eavConfig; + + /** + * @var MetadataPool + */ + private $metadataPool; + + /** + * @param Config $eavConfig + * @param MetadataPool $metadataPool + */ + public function __construct( + Config $eavConfig, + MetadataPool $metadataPool + ) { + $this->eavConfig = $eavConfig; + $this->metadataPool = $metadataPool; + } + + /** + * @param Select $select + * @return Select + */ + public function process(Select $select) + { + $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); + $statusAttribute = $this->eavConfig->getAttribute(Product::ENTITY, ProductInterface::STATUS); + + $select->join( + ['status_attr' => $statusAttribute->getBackendTable()], + sprintf('status_attr.%s = %s.%1$s', $linkField, self::PRODUCT_TABLE_ALIAS), + [] + ) + ->where('status_attr.attribute_id = ?', $statusAttribute->getAttributeId()) + ->where('status_attr.value = ?', Status::STATUS_ENABLED); + + return $select; + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/StockTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/StockTest.php index ec9cb624db79af510c2625ffee2680ede7653a19..32d62fd7a998e7bf820b7b0c26b6a7202350c26a 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/StockTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/StockTest.php @@ -125,4 +125,17 @@ class StockTest extends \PHPUnit_Framework_TestCase $stockData = $object->getStockData(); $this->assertEquals(0, $stockData['qty']); } + + public function testBeforeSaveNoStockData() + { + $object = new \Magento\Framework\DataObject( + [ + self::ATTRIBUTE_NAME => ['is_in_stock' => 1, 'qty' => 0] + ] + ); + + $this->model->beforeSave($object); + $this->assertNull($object->getStockData()); + $this->assertNull($object->getData(self::ATTRIBUTE_NAME)); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CompositeBaseSelectProcessorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CompositeBaseSelectProcessorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d296474c202f091b4c1435453ec7941007e10885 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CompositeBaseSelectProcessorTest.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Test\Unit\Model\ResourceModel\Product; + +use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface; +use Magento\Catalog\Model\ResourceModel\Product\CompositeBaseSelectProcessor; +use Magento\Framework\DB\Select; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class CompositeBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + protected function setUp() + { + $this->objectManager = new ObjectManager($this); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + */ + public function testInitializeWithWrongProcessorInstance() + { + $processorValid = $this->getMock(BaseSelectProcessorInterface::class); + $processorInvalid = $this->getMock(\stdClass::class); + + $this->objectManager->getObject(CompositeBaseSelectProcessor::class, [ + 'baseSelectProcessors' => [$processorValid, $processorInvalid], + ]); + } + + public function testProcess() + { + $select = $this->getMockBuilder(Select::class)->disableOriginalConstructor()->getMock(); + + $processorFirst = $this->getMock(BaseSelectProcessorInterface::class); + $processorFirst->expects($this->once())->method('process')->with($select)->willReturn($select); + + $processorSecond = $this->getMock(BaseSelectProcessorInterface::class); + $processorSecond->expects($this->once())->method('process')->with($select)->willReturn($select); + + /** @var CompositeBaseSelectProcessor $baseSelectProcessors */ + $baseSelectProcessors = $this->objectManager->getObject(CompositeBaseSelectProcessor::class, [ + 'baseSelectProcessors' => [$processorFirst, $processorSecond], + ]); + $this->assertEquals($select, $baseSelectProcessors->process($select)); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/StatusBaseSelectProcessorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/StatusBaseSelectProcessorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0909f754a01c2c937e8c3692c52b1a256a27b0c3 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/StatusBaseSelectProcessorTest.php @@ -0,0 +1,102 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Test\Unit\Model\ResourceModel\Product; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface; +use Magento\Catalog\Model\ResourceModel\Product\StatusBaseSelectProcessor; +use Magento\Eav\Model\Config; +use Magento\Eav\Model\Entity\Attribute\AttributeInterface; +use Magento\Framework\DB\Select; +use Magento\Framework\EntityManager\EntityMetadataInterface; +use Magento\Framework\EntityManager\MetadataPool; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class StatusBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Config|\PHPUnit_Framework_MockObject_MockObject + */ + private $eavConfig; + + /** + * @var MetadataPool|\PHPUnit_Framework_MockObject_MockObject + */ + private $metadataPool; + + /** + * @var Select|\PHPUnit_Framework_MockObject_MockObject + */ + private $select; + + /** + * @var StatusBaseSelectProcessor + */ + private $statusBaseSelectProcessor; + + protected function setUp() + { + $this->eavConfig = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock(); + $this->metadataPool = $this->getMockBuilder(MetadataPool::class)->disableOriginalConstructor()->getMock(); + $this->select = $this->getMockBuilder(Select::class)->disableOriginalConstructor()->getMock(); + + $this->statusBaseSelectProcessor = (new ObjectManager($this))->getObject(StatusBaseSelectProcessor::class, [ + 'eavConfig' => $this->eavConfig, + 'metadataPool' => $this->metadataPool, + ]); + } + + public function testProcess() + { + $linkField = 'link_field'; + $backendTable = 'backend_table'; + $attributeId = 'attribute_id'; + + $metadata = $this->getMock(EntityMetadataInterface::class); + $metadata->expects($this->once()) + ->method('getLinkField') + ->willReturn($linkField); + $this->metadataPool->expects($this->once()) + ->method('getMetadata') + ->with(ProductInterface::class) + ->willReturn($metadata); + + $statusAttribute = $this->getMockBuilder(AttributeInterface::class) + ->setMethods(['getBackendTable', 'getAttributeId']) + ->getMock(); + $statusAttribute->expects($this->once()) + ->method('getBackendTable') + ->willReturn($backendTable); + $statusAttribute->expects($this->once()) + ->method('getAttributeId') + ->willReturn($attributeId); + $this->eavConfig->expects($this->once()) + ->method('getAttribute') + ->with(Product::ENTITY, ProductInterface::STATUS) + ->willReturn($statusAttribute); + + $this->select->expects($this->once()) + ->method('join') + ->with( + ['status_attr' => $backendTable], + sprintf('status_attr.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + [] + ) + ->willReturnSelf(); + $this->select->expects($this->at(1)) + ->method('where') + ->with('status_attr.attribute_id = ?', $attributeId) + ->willReturnSelf(); + $this->select->expects($this->at(2)) + ->method('where') + ->with('status_attr.value = ?', Status::STATUS_ENABLED) + ->willReturnSelf(); + + $this->assertEquals($this->select, $this->statusBaseSelectProcessor->process($this->select)); + } +} diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index d191f0332f5f28d28f22e981f8ebc74f0c0c8b98..6b39520ae021e9eb3bfafa20bda03e42c7db907a 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -837,4 +837,12 @@ <type name="Magento\Quote\Model\Quote\Item\ToOrderItem"> <plugin name="copy_quote_files_to_order" type="Magento\Catalog\Model\Plugin\QuoteItemProductOption"/> </type> + <preference for="Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface" type="Magento\Catalog\Model\ResourceModel\Product\CompositeBaseSelectProcessor" /> + <type name="Magento\Catalog\Model\ResourceModel\Product\CompositeBaseSelectProcessor"> + <arguments> + <argument name="baseSelectProcessors" xsi:type="array"> + <item name="status" xsi:type="object">Magento\Catalog\Model\ResourceModel\Product\StatusBaseSelectProcessor</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php new file mode 100644 index 0000000000000000000000000000000000000000..829fa8decda7d74b554810ba17118faba2ca970c --- /dev/null +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php @@ -0,0 +1,51 @@ +<?php +/** + * + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogInventory\Model\ResourceModel\Product; + +use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface; +use Magento\CatalogInventory\Model\Stock; +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\Select; + +/** + * Class StockStatusBaseSelectProcessor + */ +class StockStatusBaseSelectProcessor implements BaseSelectProcessorInterface +{ + /** + * @var ResourceConnection + */ + private $resource; + + /** + * @param ResourceConnection $resource + */ + public function __construct(ResourceConnection $resource) + { + $this->resource = $resource; + } + + /** + * Add stock item filter to selects + * + * @param Select $select + * @return Select + */ + public function process(Select $select) + { + $stockStatusTable = $this->resource->getTableName('cataloginventory_stock_status'); + + /** @var Select $select */ + $select->join( + ['stock' => $stockStatusTable], + sprintf('stock.product_id = %s.entity_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + [] + ) + ->where('stock.stock_status = ?', Stock::STOCK_IN_STOCK); + return $select; + } +} diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4756e42ffe602bfc3b258656e0f2abe490a3acc1 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php @@ -0,0 +1,69 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogInventory\Test\Unit\Model\ResourceModel\Product; + +use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface; +use Magento\CatalogInventory\Model\ResourceModel\Product\StockStatusBaseSelectProcessor; +use Magento\CatalogInventory\Model\Stock; +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\Select; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class StockStatusBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ResourceConnection|\PHPUnit_Framework_MockObject_MockObject + */ + private $resource; + + /** + * @var Select|\PHPUnit_Framework_MockObject_MockObject + */ + private $select; + + /** + * @var StockStatusBaseSelectProcessor + */ + private $stockStatusBaseSelectProcessor; + + protected function setUp() + { + $this->resource = $this->getMockBuilder(ResourceConnection::class)->disableOriginalConstructor()->getMock(); + $this->select = $this->getMockBuilder(Select::class)->disableOriginalConstructor()->getMock(); + + $this->stockStatusBaseSelectProcessor = (new ObjectManager($this))->getObject( + StockStatusBaseSelectProcessor::class, + [ + 'resource' => $this->resource, + ] + ); + } + + public function testProcess() + { + $tableName = 'table_name'; + + $this->resource->expects($this->once()) + ->method('getTableName') + ->with('cataloginventory_stock_status') + ->willReturn($tableName); + + $this->select->expects($this->once()) + ->method('join') + ->with( + ['stock' => $tableName], + sprintf('stock.product_id = %s.entity_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + [] + ) + ->willReturnSelf(); + $this->select->expects($this->once()) + ->method('where') + ->with('stock.stock_status = ?', Stock::STOCK_IN_STOCK) + ->willReturnSelf(); + + $this->stockStatusBaseSelectProcessor->process($this->select); + } +} diff --git a/app/code/Magento/CatalogInventory/etc/di.xml b/app/code/Magento/CatalogInventory/etc/di.xml index 71b42ef89f73ce981f25393179fbbd05f59a4d08..e3ca5c01cedab6b5041a16248308208b3cccbcf5 100644 --- a/app/code/Magento/CatalogInventory/etc/di.xml +++ b/app/code/Magento/CatalogInventory/etc/di.xml @@ -79,4 +79,11 @@ <argument name="indexerProcessor" xsi:type="object">Magento\CatalogInventory\Model\Indexer\Stock\Processor</argument> </arguments> </type> + <type name="Magento\Catalog\Model\ResourceModel\Product\CompositeBaseSelectProcessor"> + <arguments> + <argument name="baseSelectProcessors" xsi:type="array"> + <item name="stock_status" xsi:type="object">Magento\CatalogInventory\Model\ResourceModel\Product\StockStatusBaseSelectProcessor</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php b/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php index 7d8d44dcbb68ad2539f0556fb7aec8eebe0caa2e..55b76eb225028a1a3d96d115066a4abc4b78fd60 100644 --- a/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php +++ b/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php @@ -6,7 +6,8 @@ namespace Magento\CatalogRule\Model\ResourceModel\Product; use Magento\Catalog\Api\Data\ProductInterface; -use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\Select; use Magento\Catalog\Model\ResourceModel\Product\LinkedProductSelectBuilderInterface; @@ -42,6 +43,11 @@ class LinkedProductSelectBuilderByCatalogRulePrice implements LinkedProductSelec */ private $metadataPool; + /** + * @var BaseSelectProcessorInterface + */ + private $baseSelectProcessor; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\ResourceConnection $resourceConnection @@ -49,6 +55,7 @@ class LinkedProductSelectBuilderByCatalogRulePrice implements LinkedProductSelec * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool + * @param BaseSelectProcessorInterface $baseSelectProcessor */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, @@ -56,7 +63,8 @@ class LinkedProductSelectBuilderByCatalogRulePrice implements LinkedProductSelec \Magento\Customer\Model\Session $customerSession, \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, - \Magento\Framework\EntityManager\MetadataPool $metadataPool + \Magento\Framework\EntityManager\MetadataPool $metadataPool, + BaseSelectProcessorInterface $baseSelectProcessor = null ) { $this->storeManager = $storeManager; $this->resource = $resourceConnection; @@ -64,6 +72,8 @@ class LinkedProductSelectBuilderByCatalogRulePrice implements LinkedProductSelec $this->dateTime = $dateTime; $this->localeDate = $localeDate; $this->metadataPool = $metadataPool; + $this->baseSelectProcessor = (null !== $baseSelectProcessor) + ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); } /** @@ -76,25 +86,28 @@ class LinkedProductSelectBuilderByCatalogRulePrice implements LinkedProductSelec $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); $productTable = $this->resource->getTableName('catalog_product_entity'); - return [$this->resource->getConnection()->select() - ->from(['parent' => $productTable], '') - ->joinInner( - ['link' => $this->resource->getTableName('catalog_product_relation')], - "link.parent_id = parent.$linkField", - [] - )->joinInner( - ['child' => $productTable], - "child.entity_id = link.child_id", - ['entity_id'] - )->joinInner( - ['t' => $this->resource->getTableName('catalogrule_product_price')], - 't.product_id = child.entity_id', - [] - )->where('parent.entity_id = ? ', $productId) + $priceSelect = $this->resource->getConnection()->select() + ->from(['parent' => $productTable], '') + ->joinInner( + ['link' => $this->resource->getTableName('catalog_product_relation')], + "link.parent_id = parent.$linkField", + [] + )->joinInner( + [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], + sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + ['entity_id'] + )->joinInner( + ['t' => $this->resource->getTableName('catalogrule_product_price')], + sprintf('t.product_id = %s.%s', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), + [] + )->where('parent.entity_id = ?', $productId) ->where('t.website_id = ?', $this->storeManager->getStore()->getWebsiteId()) ->where('t.customer_group_id = ?', $this->customerSession->getCustomerGroupId()) ->where('t.rule_date = ?', $currentDate) ->order('t.rule_price ' . Select::SQL_ASC) - ->limit(1)]; + ->limit(1); + $priceSelect = $this->baseSelectProcessor->process($priceSelect); + + return [$priceSelect]; } } diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js b/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js index 2d6fa460ef66d26d106ad9417ffdf8d3548a3d00..3ec34cd96574bc90e5b0f8bd3bf552a877444ab0 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js @@ -44,6 +44,13 @@ define( addressData.region.region_code = region['code']; addressData.region.region = region['name']; } + } else if ( + !addressData.region_id + && countryData()[addressData.country_id] + && countryData()[addressData.country_id]['regions'] + ) { + addressData.region.region_code = ''; + addressData.region.region = ''; } delete addressData.region_id; diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js index bee4480b0dfb1c9db669d53f5091bb1d3564237a..9a3685b212b435e8c03adb7be2cd7a182e591b87 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js @@ -22,7 +22,7 @@ define([], function () { return { email: addressData.email, countryId: addressData['country_id'] || addressData.countryId || window.checkoutConfig.defaultCountryId, - regionId: regionId, + regionId: regionId || addressData.regionId, regionCode: (addressData.region) ? addressData.region.region_code : null, region: (addressData.region) ? addressData.region.region : null, customerId: addressData.customer_id, @@ -30,7 +30,7 @@ define([], function () { company: addressData.company, telephone: addressData.telephone, fax: addressData.fax, - postcode: addressData.postcode ? addressData.postcode : window.checkoutConfig.defaultPostcode, + postcode: addressData.postcode ? addressData.postcode : window.checkoutConfig.defaultPostcode || undefined, city: addressData.city, firstname: addressData.firstname, lastname: addressData.lastname, diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js index 420d50b83478a91ab38b6a333a681f119b6db49e..c49960ecfb91dec735239c8bc1cc88f7ffebfab0 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js @@ -176,7 +176,7 @@ define( address; if (this.validateAddressData(addressFlat)) { - addressFlat = $.extend(true, {}, quote.shippingAddress(), addressFlat); + addressFlat = uiRegistry.get('checkoutProvider').shippingAddress; address = addressConverter.formAddressDataToQuoteAddress(addressFlat); selectShippingAddress(address); } diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProvider.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProvider.php index dcb75fe725dc20d74aa245831e8046dbd9665949..872538d9babab02aec00763ee317298f9c93697e 100644 --- a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProvider.php +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProvider.php @@ -18,26 +18,6 @@ class ConfigurableOptionsProvider implements ConfigurableOptionsProviderInterfac /** @var Configurable */ private $configurable; - /** - * @var RequestSafetyInterface - */ - private $requestSafety; - - /** - * @var ResourceConnection - */ - private $resource; - - /** - * @var LinkedProductSelectBuilderInterface - */ - private $linkedProductSelectBuilder; - - /** - * @var CollectionFactory - */ - private $collectionFactory; - /** * @var ProductInterface[] */ @@ -49,6 +29,7 @@ class ConfigurableOptionsProvider implements ConfigurableOptionsProviderInterfac * @param LinkedProductSelectBuilderInterface $linkedProductSelectBuilder * @param CollectionFactory $collectionFactory * @param RequestSafetyInterface $requestSafety + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( Configurable $configurable, @@ -58,10 +39,6 @@ class ConfigurableOptionsProvider implements ConfigurableOptionsProviderInterfac RequestSafetyInterface $requestSafety ) { $this->configurable = $configurable; - $this->resource = $resourceConnection; - $this->linkedProductSelectBuilder = $linkedProductSelectBuilder; - $this->collectionFactory = $collectionFactory; - $this->requestSafety = $requestSafety; } /** @@ -70,17 +47,7 @@ class ConfigurableOptionsProvider implements ConfigurableOptionsProviderInterfac public function getProducts(ProductInterface $product) { if (!isset($this->products[$product->getId()])) { - if ($this->requestSafety->isSafeMethod()) { - $productIds = $this->resource->getConnection()->fetchCol( - '(' . implode(') UNION (', $this->linkedProductSelectBuilder->build($product->getId())) . ')' - ); - - $this->products[$product->getId()] = $this->collectionFactory->create() - ->addAttributeToSelect(['price', 'special_price']) - ->addIdFilter($productIds); - } else { - $this->products[$product->getId()] = $this->configurable->getUsedProducts($product); - } + $this->products[$product->getId()] = $this->configurable->getUsedProducts($product); } return $this->products[$product->getId()]; } diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProviderInterface.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProviderInterface.php index c7ac9446f42e306b78badec5f4b0825ce8c6f6c1..c0f2c218cc77c80a8e6785aba97431baea793975 100644 --- a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProviderInterface.php +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProviderInterface.php @@ -10,6 +10,7 @@ use Magento\Catalog\Api\Data\ProductInterface; /** * Provide configurable sub-products for price calculation + * @api */ interface ConfigurableOptionsProviderInterface { diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurablePriceResolver.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurablePriceResolver.php index 75d08b5aa419bdec6d9db0c3112f2aa1b7e836a6..68e82ed76a23fbdda404c32eb7406d3117b3cd0e 100644 --- a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurablePriceResolver.php +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurablePriceResolver.php @@ -6,7 +6,6 @@ namespace Magento\ConfigurableProduct\Pricing\Price; -use Magento\Catalog\Model\Product; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; use Magento\Framework\App\ObjectManager; use Magento\Framework\Pricing\PriceCurrencyInterface; @@ -29,23 +28,27 @@ class ConfigurablePriceResolver implements PriceResolverInterface protected $configurable; /** - * @var ConfigurableOptionsProviderInterface + * @var LowestPriceOptionsProviderInterface */ - private $configurableOptionsProvider; + private $lowestPriceOptionsProvider; /** * @param PriceResolverInterface $priceResolver * @param Configurable $configurable * @param PriceCurrencyInterface $priceCurrency + * @param LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider */ public function __construct( PriceResolverInterface $priceResolver, Configurable $configurable, - PriceCurrencyInterface $priceCurrency + PriceCurrencyInterface $priceCurrency, + LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider = null ) { $this->priceResolver = $priceResolver; $this->configurable = $configurable; $this->priceCurrency = $priceCurrency; + $this->lowestPriceOptionsProvider = $lowestPriceOptionsProvider ?: + ObjectManager::getInstance()->get(LowestPriceOptionsProviderInterface::class); } /** @@ -57,7 +60,7 @@ class ConfigurablePriceResolver implements PriceResolverInterface { $price = null; - foreach ($this->getConfigurableOptionsProvider()->getProducts($product) as $subProduct) { + foreach ($this->lowestPriceOptionsProvider->getProducts($product) as $subProduct) { $productPrice = $this->priceResolver->resolvePrice($subProduct); $price = $price ? min($price, $productPrice) : $productPrice; } @@ -69,17 +72,4 @@ class ConfigurablePriceResolver implements PriceResolverInterface return (float)$price; } - - /** - * @return \Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProviderInterface - * @deprecated - */ - private function getConfigurableOptionsProvider() - { - if (null === $this->configurableOptionsProvider) { - $this->configurableOptionsProvider = ObjectManager::getInstance() - ->get(ConfigurableOptionsProviderInterface::class); - } - return $this->configurableOptionsProvider; - } } diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableRegularPrice.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableRegularPrice.php index 14b788258ab75502183aaf0b3f842b1943fcec2d..7a710e2caacc96f0a20eae124d973de9fa6a4c49 100644 --- a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableRegularPrice.php +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableRegularPrice.php @@ -44,22 +44,31 @@ class ConfigurableRegularPrice extends AbstractPrice implements ConfigurableRegu */ private $configurableOptionsProvider; + /** + * @var LowestPriceOptionsProviderInterface + */ + private $lowestPriceOptionsProvider; + /** * @param \Magento\Framework\Pricing\SaleableInterface $saleableItem * @param float $quantity * @param \Magento\Framework\Pricing\Adjustment\CalculatorInterface $calculator * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency * @param PriceResolverInterface $priceResolver + * @param LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider */ public function __construct( \Magento\Framework\Pricing\SaleableInterface $saleableItem, $quantity, \Magento\Framework\Pricing\Adjustment\CalculatorInterface $calculator, \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency, - PriceResolverInterface $priceResolver + PriceResolverInterface $priceResolver, + LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider = null ) { parent::__construct($saleableItem, $quantity, $calculator, $priceCurrency); $this->priceResolver = $priceResolver; + $this->lowestPriceOptionsProvider = $lowestPriceOptionsProvider ?: + ObjectManager::getInstance()->get(LowestPriceOptionsProviderInterface::class); } /** @@ -88,7 +97,6 @@ class ConfigurableRegularPrice extends AbstractPrice implements ConfigurableRegu public function getMaxRegularAmount() { if (null === $this->maxRegularAmount) { - $this->maxRegularAmount = $this->doGetMaxRegularAmount(); $this->maxRegularAmount = $this->doGetMaxRegularAmount() ?: false; } return $this->maxRegularAmount; @@ -96,7 +104,7 @@ class ConfigurableRegularPrice extends AbstractPrice implements ConfigurableRegu } /** - * Get max regular amount. Template method + * Get max regular amount * * @return \Magento\Framework\Pricing\Amount\AmountInterface */ @@ -124,14 +132,14 @@ class ConfigurableRegularPrice extends AbstractPrice implements ConfigurableRegu } /** - * Get min regular amount. Template method + * Get min regular amount * * @return \Magento\Framework\Pricing\Amount\AmountInterface */ protected function doGetMinRegularAmount() { $minAmount = null; - foreach ($this->getUsedProducts() as $product) { + foreach ($this->lowestPriceOptionsProvider->getProducts($this->product) as $product) { $childPriceAmount = $product->getPriceInfo()->getPrice(self::PRICE_CODE)->getAmount(); if (!$minAmount || ($childPriceAmount->getValue() < $minAmount->getValue())) { $minAmount = $childPriceAmount; diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProvider.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..1b758866100eb8f52faa371e4bc1695ce385703f --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProvider.php @@ -0,0 +1,63 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\ConfigurableProduct\Pricing\Price; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Model\ResourceModel\Product\LinkedProductSelectBuilderInterface; +use Magento\Framework\App\ResourceConnection; +use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory; + +/** + * Retrieve list of products where each product contains lower price than others at least for one possible price type + */ +class LowestPriceOptionsProvider implements LowestPriceOptionsProviderInterface +{ + /** + * @var ResourceConnection + */ + private $resource; + + /** + * @var LinkedProductSelectBuilderInterface + */ + private $linkedProductSelectBuilder; + + /** + * @var CollectionFactory + */ + private $collectionFactory; + + /** + * @param ResourceConnection $resourceConnection + * @param LinkedProductSelectBuilderInterface $linkedProductSelectBuilder + * @param CollectionFactory $collectionFactory + */ + public function __construct( + ResourceConnection $resourceConnection, + LinkedProductSelectBuilderInterface $linkedProductSelectBuilder, + CollectionFactory $collectionFactory + ) { + $this->resource = $resourceConnection; + $this->linkedProductSelectBuilder = $linkedProductSelectBuilder; + $this->collectionFactory = $collectionFactory; + } + + /** + * {@inheritdoc} + */ + public function getProducts(ProductInterface $product) + { + $productIds = $this->resource->getConnection()->fetchCol( + '(' . implode(') UNION (', $this->linkedProductSelectBuilder->build($product->getId())) . ')' + ); + + $lowestPriceChildProducts = $this->collectionFactory->create() + ->addAttributeToSelect(['price', 'special_price']) + ->addIdFilter($productIds) + ->getItems(); + return $lowestPriceChildProducts; + } +} diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProviderInterface.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProviderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..c0989a929be55ce46bdaa3451ba88a8a3ae8272a --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProviderInterface.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\ConfigurableProduct\Pricing\Price; + +use Magento\Catalog\Api\Data\ProductInterface; + +/** + * Retrieve list of products where each product contains lower price than others at least for one possible price type + * @api + */ +interface LowestPriceOptionsProviderInterface +{ + /** + * @param ProductInterface $product + * @return \Magento\Catalog\Api\Data\ProductInterface[] + */ + public function getProducts(\Magento\Catalog\Api\Data\ProductInterface $product); +} diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Render/FinalPriceBox.php b/app/code/Magento/ConfigurableProduct/Pricing/Render/FinalPriceBox.php index 16a296a3554548d31f1692f397cd0124e272a1af..19bf0eee888f181902824505a2808f8ae5106c15 100644 --- a/app/code/Magento/ConfigurableProduct/Pricing/Render/FinalPriceBox.php +++ b/app/code/Magento/ConfigurableProduct/Pricing/Render/FinalPriceBox.php @@ -8,6 +8,8 @@ namespace Magento\ConfigurableProduct\Pricing\Render; use Magento\Catalog\Pricing\Price\FinalPrice; use Magento\Catalog\Pricing\Price\RegularPrice; use Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProviderInterface; +use Magento\ConfigurableProduct\Pricing\Price\LowestPriceOptionsProviderInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Pricing\Price\PriceInterface; use Magento\Framework\Pricing\Render\RendererPool; use Magento\Framework\Pricing\SaleableInterface; @@ -16,9 +18,9 @@ use Magento\Framework\View\Element\Template\Context; class FinalPriceBox extends \Magento\Catalog\Pricing\Render\FinalPriceBox { /** - * @var ConfigurableOptionsProviderInterface + * @var LowestPriceOptionsProviderInterface */ - private $configurableOptionsProvider; + private $lowestPriceOptionsProvider; /** * @param Context $context @@ -27,6 +29,8 @@ class FinalPriceBox extends \Magento\Catalog\Pricing\Render\FinalPriceBox * @param RendererPool $rendererPool * @param ConfigurableOptionsProviderInterface $configurableOptionsProvider * @param array $data + * @param LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( Context $context, @@ -34,10 +38,12 @@ class FinalPriceBox extends \Magento\Catalog\Pricing\Render\FinalPriceBox PriceInterface $price, RendererPool $rendererPool, ConfigurableOptionsProviderInterface $configurableOptionsProvider, - array $data = [] + array $data = [], + LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider = null ) { - $this->configurableOptionsProvider = $configurableOptionsProvider; parent::__construct($context, $saleableItem, $price, $rendererPool, $data); + $this->lowestPriceOptionsProvider = $lowestPriceOptionsProvider ?: + ObjectManager::getInstance()->get(LowestPriceOptionsProviderInterface::class); } /** @@ -48,7 +54,7 @@ class FinalPriceBox extends \Magento\Catalog\Pricing\Render\FinalPriceBox public function hasSpecialPrice() { $product = $this->getSaleableItem(); - foreach ($this->configurableOptionsProvider->getProducts($product) as $subProduct) { + foreach ($this->lowestPriceOptionsProvider->getProducts($product) as $subProduct) { $regularPrice = $subProduct->getPriceInfo()->getPrice(RegularPrice::PRICE_CODE)->getValue(); $finalPrice = $subProduct->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE)->getValue(); if ($finalPrice < $regularPrice) { diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Price/ConfigurablePriceResolverTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Price/ConfigurablePriceResolverTest.php index 0e2cfc0630226d500db55db0fd0fb0b60bb4d121..8db61bb5e0a4322ff3d614348616dfc0e2f34e27 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Price/ConfigurablePriceResolverTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Price/ConfigurablePriceResolverTest.php @@ -5,13 +5,15 @@ */ namespace Magento\ConfigurableProduct\Test\Unit\Pricing\Price; -use Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProviderInterface; +use Magento\ConfigurableProduct\Pricing\Price\LowestPriceOptionsProviderInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; class ConfigurablePriceResolverTest extends \PHPUnit_Framework_TestCase { - /** @var ConfigurableOptionsProviderInterface */ - private $cofigurableOptionProvider; + /** + * @var LowestPriceOptionsProviderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $lowestPriceOptionsProvider; /** * @var \Magento\ConfigurableProduct\Pricing\Price\ConfigurablePriceResolver @@ -19,12 +21,12 @@ class ConfigurablePriceResolverTest extends \PHPUnit_Framework_TestCase protected $resolver; /** - * @var PHPUnit_Framework_MockObject_MockObject | \Magento\ConfigurableProduct\Model\Product\Type\Configurable + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\ConfigurableProduct\Model\Product\Type\Configurable */ protected $configurable; /** - * @var PHPUnit_Framework_MockObject_MockObject | \Magento\ConfigurableProduct\Pricing\Price\PriceResolverInterface + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\ConfigurableProduct\Pricing\Price\PriceResolverInterface */ protected $priceResolver; @@ -36,8 +38,7 @@ class ConfigurablePriceResolverTest extends \PHPUnit_Framework_TestCase $className = \Magento\ConfigurableProduct\Pricing\Price\PriceResolverInterface::class; $this->priceResolver = $this->getMockForAbstractClass($className, [], '', false, true, true, ['resolvePrice']); - $this->cofigurableOptionProvider = $this->getMockBuilder(ConfigurableOptionsProviderInterface::class) - ->disableOriginalConstructor()->getMock(); + $this->lowestPriceOptionsProvider = $this->getMock(LowestPriceOptionsProviderInterface::class); $objectManager = new ObjectManager($this); $this->resolver = $objectManager->getObject( @@ -45,7 +46,7 @@ class ConfigurablePriceResolverTest extends \PHPUnit_Framework_TestCase [ 'priceResolver' => $this->priceResolver, 'configurable' => $this->configurable, - 'configurableOptionsProvider' => $this->cofigurableOptionProvider, + 'lowestPriceOptionsProvider' => $this->lowestPriceOptionsProvider, ] ); } @@ -63,7 +64,7 @@ class ConfigurablePriceResolverTest extends \PHPUnit_Framework_TestCase $product->expects($this->once())->method('getSku')->willReturn('Kiwi'); - $this->cofigurableOptionProvider->expects($this->once())->method('getProducts')->willReturn([]); + $this->lowestPriceOptionsProvider->expects($this->once())->method('getProducts')->willReturn([]); $this->resolver->resolvePrice($product); } @@ -83,8 +84,11 @@ class ConfigurablePriceResolverTest extends \PHPUnit_Framework_TestCase $product->expects($this->never())->method('getSku'); - $this->cofigurableOptionProvider->expects($this->once())->method('getProducts')->willReturn([$product]); - $this->priceResolver->expects($this->atLeastOnce())->method('resolvePrice')->willReturn($price); + $this->lowestPriceOptionsProvider->expects($this->once())->method('getProducts')->willReturn([$product]); + $this->priceResolver->expects($this->once()) + ->method('resolvePrice') + ->with($product) + ->willReturn($price); $this->assertEquals($expectedValue, $this->resolver->resolvePrice($product)); } diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/FinalPriceBoxTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/FinalPriceBoxTest.php index 4dbcfed5315252c62494b6ede30d4d14f9a598b2..b102e1d81f48ea421ce29a7cd914a758e94ccb68 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/FinalPriceBoxTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/FinalPriceBoxTest.php @@ -7,8 +7,9 @@ namespace Magento\ConfigurableProduct\Test\Unit\Pricing\Render; use Magento\Catalog\Pricing\Price\FinalPrice; use Magento\Catalog\Pricing\Price\RegularPrice; -use Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProviderInterface; +use Magento\ConfigurableProduct\Pricing\Price\LowestPriceOptionsProviderInterface; use Magento\ConfigurableProduct\Pricing\Render\FinalPriceBox; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase { @@ -33,9 +34,9 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase private $rendererPool; /** - * @var ConfigurableOptionsProviderInterface|\PHPUnit_Framework_MockObject_MockObject + * @var LowestPriceOptionsProviderInterface|\PHPUnit_Framework_MockObject_MockObject */ - private $configurableOptionsProvider; + private $lowestPriceOptionsProvider; /** * @var FinalPriceBox @@ -59,15 +60,18 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); - $this->configurableOptionsProvider = $this->getMockBuilder(ConfigurableOptionsProviderInterface::class) + $this->lowestPriceOptionsProvider = $this->getMockBuilder(LowestPriceOptionsProviderInterface::class) ->getMockForAbstractClass(); - $this->model = new FinalPriceBox( - $this->context, - $this->saleableItem, - $this->price, - $this->rendererPool, - $this->configurableOptionsProvider + $this->model = (new ObjectManager($this))->getObject( + FinalPriceBox::class, + [ + 'context' => $this->context, + 'saleableItem' => $this->saleableItem, + 'price' => $this->price, + 'rendererPool' => $this->rendererPool, + 'lowestPriceOptionsProvider' => $this->lowestPriceOptionsProvider, + ] ); } @@ -115,7 +119,7 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase ->method('getPriceInfo') ->willReturn($priceInfoMock); - $this->configurableOptionsProvider->expects($this->once()) + $this->lowestPriceOptionsProvider->expects($this->once()) ->method('getProducts') ->with($this->saleableItem) ->willReturn([$productMock]); diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml index 89b271de838f992e9acd93ecdd27bc321f59d54e..b4d63d9d0245f84b3ecbae128e5254e8f9bf213a 100644 --- a/app/code/Magento/ConfigurableProduct/etc/di.xml +++ b/app/code/Magento/ConfigurableProduct/etc/di.xml @@ -13,6 +13,7 @@ <preference for="Magento\ConfigurableProduct\Api\Data\OptionValueInterface" type="Magento\ConfigurableProduct\Model\Product\Type\Configurable\OptionValue" /> <preference for="Magento\ConfigurableProduct\Api\Data\ConfigurableItemOptionValueInterface" type="Magento\ConfigurableProduct\Model\Quote\Item\ConfigurableItemOptionValue" /> <preference for="Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProviderInterface" type="Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProvider" /> + <preference for="Magento\ConfigurableProduct\Pricing\Price\LowestPriceOptionsProviderInterface" type="Magento\ConfigurableProduct\Pricing\Price\LowestPriceOptionsProvider" /> <type name="Magento\CatalogInventory\Model\Quote\Item\QuantityValidator\Initializer\Option"> <plugin name="configurable_product" type="Magento\ConfigurableProduct\Model\Quote\Item\QuantityValidator\Initializer\Option\Plugin\ConfigurableProduct" sortOrder="50" /> diff --git a/app/code/Magento/Developer/Model/View/Asset/PreProcessor/FrontendCompilation.php b/app/code/Magento/Developer/Model/View/Asset/PreProcessor/FrontendCompilation.php index 4573f15b016fa47bab5cc0fa7c7010644c4ada6e..8cd04f7d1e4c54804ba32c3c8b5235f9da3dd1db 100644 --- a/app/code/Magento/Developer/Model/View/Asset/PreProcessor/FrontendCompilation.php +++ b/app/code/Magento/Developer/Model/View/Asset/PreProcessor/FrontendCompilation.php @@ -74,10 +74,6 @@ class FrontendCompilation implements PreProcessorInterface */ public function process(PreProcessor\Chain $chain) { - $content = $chain->getContent(); - if (trim($content) !== '') { - return; - } try { $this->lockerProcess->lockProcess($this->lockName); @@ -88,7 +84,7 @@ class FrontendCompilation implements PreProcessorInterface /** @var FallbackContext $context */ $context = $chain->getAsset()->getContext(); - $result = $this->processContent($path, $content, $module, $context); + $result = $this->processContent($path, $chain->getContent(), $module, $context); $chain->setContent($result['content']); $chain->setContentType($result['sourceType']); } finally { @@ -107,14 +103,14 @@ class FrontendCompilation implements PreProcessorInterface */ private function processContent($path, $content, $module, FallbackContext $context) { - $sourceType = '#\.' . preg_quote(pathinfo($path, PATHINFO_EXTENSION), '#') . '$#'; + $sourceTypePattern = '#\.' . preg_quote(pathinfo($path, PATHINFO_EXTENSION), '#') . '$#'; foreach ($this->alternativeSource->getAlternativesExtensionsNames() as $name) { $asset = $this->assetBuilder->setArea($context->getAreaCode()) ->setTheme($context->getThemePath()) ->setLocale($context->getLocale()) ->setModule($module) - ->setPath(preg_replace($sourceType, '.' . $name, $path)) + ->setPath(preg_replace($sourceTypePattern, '.' . $name, $path)) ->build(); $processedContent = $this->assetSource->getContent($asset); @@ -129,7 +125,7 @@ class FrontendCompilation implements PreProcessorInterface return [ 'content' => $content, - 'sourceType' => $sourceType + 'sourceType' => pathinfo($path, PATHINFO_EXTENSION) ]; } } diff --git a/app/code/Magento/Developer/Test/Unit/Model/View/Asset/PreProcessor/FrontendCompilationTest.php b/app/code/Magento/Developer/Test/Unit/Model/View/Asset/PreProcessor/FrontendCompilationTest.php index 97f0b1d5a6bdb081a47f22884f6dac93b3a743f1..b43d91c5e4dc6bc7768c47b1f8599c73b5855932 100644 --- a/app/code/Magento/Developer/Test/Unit/Model/View/Asset/PreProcessor/FrontendCompilationTest.php +++ b/app/code/Magento/Developer/Test/Unit/Model/View/Asset/PreProcessor/FrontendCompilationTest.php @@ -189,38 +189,6 @@ class FrontendCompilationTest extends \PHPUnit_Framework_TestCase $frontendCompilation->process($this->getChainMockExpects('', 1, 1, $newContentType)); } - /** - * Run test for process method (content not empty) - */ - public function testProcessContentNotEmpty() - { - $chainMock = $this->getChainMock(); - $assetMock = $this->getAssetMock(); - - $chainMock->expects(self::once()) - ->method('getContent') - ->willReturn('test-content'); - - $chainMock->expects(self::never()) - ->method('getAsset') - ->willReturn($assetMock); - - $this->lockerProcessMock->expects(self::never()) - ->method('lockProcess'); - $this->lockerProcessMock->expects(self::never()) - ->method('unlockProcess'); - - $frontendCompilation = new FrontendCompilation( - $this->assetSourceMock, - $this->assetBuilderMock, - $this->alternativeSourceMock, - $this->lockerProcessMock, - 'lock' - ); - - $frontendCompilation->process($chainMock); - } - /** * @return Chain|\PHPUnit_Framework_MockObject_MockObject */ diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php index 3cdcf70cf24266ae7613e7e6f790c4b6777ff23b..f84ca33b436f91e4afca6cae6f52c8b975cf4289 100644 --- a/app/code/Magento/Quote/Model/Quote.php +++ b/app/code/Magento/Quote/Model/Quote.php @@ -2157,6 +2157,12 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C { if (!$this->getReservedOrderId()) { $this->setReservedOrderId($this->_getResource()->getReservedOrderId($this)); + } else { + //checking if reserved order id was already used for some order + //if yes reserving new one if not using old one + if ($this->_getResource()->isOrderIncrementIdUsed($this->getReservedOrderId())) { + $this->setReservedOrderId($this->_getResource()->getReservedOrderId($this)); + } } return $this; } diff --git a/app/code/Magento/Quote/Model/Quote/Address/Total/Shipping.php b/app/code/Magento/Quote/Model/Quote/Address/Total/Shipping.php index f1660c9f9d6427fb617c2de9d87ae2a8026be3aa..7d8946661476cb851f2488405708847530e99673 100644 --- a/app/code/Magento/Quote/Model/Quote/Address/Total/Shipping.php +++ b/app/code/Magento/Quote/Model/Quote/Address/Total/Shipping.php @@ -59,10 +59,8 @@ class Shipping extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal $addressWeight = $address->getWeight(); $freeMethodWeight = $address->getFreeMethodWeight(); + $addressFreeShipping = $address->getFreeShipping(); - $address->setFreeShipping( - $this->freeShipping->isFreeShipping($quote, $shippingAssignment->getItems()) - ); $total->setTotalAmount($this->getCode(), 0); $total->setBaseTotalAmount($this->getCode(), 0); @@ -98,7 +96,7 @@ class Shipping extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal $itemQty = $child->getTotalQty(); $rowWeight = $itemWeight * $itemQty; $addressWeight += $rowWeight; - if ($address->getFreeShipping() || $child->getFreeShipping() === true) { + if ($addressFreeShipping || $child->getFreeShipping() === true) { $rowWeight = 0; } elseif (is_numeric($child->getFreeShipping())) { $freeQty = $child->getFreeShipping(); @@ -116,7 +114,7 @@ class Shipping extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal $itemWeight = $item->getWeight(); $rowWeight = $itemWeight * $item->getQty(); $addressWeight += $rowWeight; - if ($address->getFreeShipping() || $item->getFreeShipping() === true) { + if ($addressFreeShipping || $item->getFreeShipping() === true) { $rowWeight = 0; } elseif (is_numeric($item->getFreeShipping())) { $freeQty = $item->getFreeShipping(); @@ -136,7 +134,7 @@ class Shipping extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal $itemWeight = $item->getWeight(); $rowWeight = $itemWeight * $item->getQty(); $addressWeight += $rowWeight; - if ($address->getFreeShipping() || $item->getFreeShipping() === true) { + if ($addressFreeShipping || $item->getFreeShipping() === true) { $rowWeight = 0; } elseif (is_numeric($item->getFreeShipping())) { $freeQty = $item->getFreeShipping(); @@ -157,6 +155,10 @@ class Shipping extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal $address->setWeight($addressWeight); $address->setFreeMethodWeight($freeMethodWeight); + $address->setFreeShipping( + $this->freeShipping->isFreeShipping($quote, $shippingAssignment->getItems()) + ); + $address->collectShippingRates(); if ($method) { diff --git a/app/code/Magento/Quote/Model/ResourceModel/Quote.php b/app/code/Magento/Quote/Model/ResourceModel/Quote.php index 241f0d6b272fc33f6b29ff4e2c069ca088c5073b..6113a1ba56ac184d59a6d0e37bd696455dce31cd 100644 --- a/app/code/Magento/Quote/Model/ResourceModel/Quote.php +++ b/app/code/Magento/Quote/Model/ResourceModel/Quote.php @@ -172,6 +172,29 @@ class Quote extends AbstractDb ->getNextValue(); } + /** + * Check if order increment ID is already used. + * Method can be used to avoid collisions of order IDs. + * + * @param int $orderIncrementId + * @return bool + */ + public function isOrderIncrementIdUsed($orderIncrementId) + { + /** @var \Magento\Framework\DB\Adapter\AdapterInterface $adapter */ + $adapter = $this->getConnection(); + $bind = [':increment_id' => $orderIncrementId]; + /** @var \Magento\Framework\DB\Select $select */ + $select = $adapter->select(); + $select->from($this->getTable('sales_order'), 'entity_id')->where('increment_id = :increment_id'); + $entity_id = $adapter->fetchOne($select, $bind); + if ($entity_id > 0) { + return true; + } + + return false; + } + /** * Mark quotes - that depend on catalog price rules - to be recollected on demand * diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php index 5165f299d45a96b7aa9b130a03747fad38955084..b54ce84fe1ac45fbee2d1b2c89a99c8546a11cab 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php @@ -314,7 +314,10 @@ class QuoteTest extends \PHPUnit_Framework_TestCase 'customerRepository' => $this->customerRepositoryMock, 'objectCopyService' => $this->objectCopyServiceMock, 'extensionAttributesJoinProcessor' => $this->extensionAttributesJoinProcessorMock, - 'customerDataFactory' => $this->customerDataFactoryMock + 'customerDataFactory' => $this->customerDataFactoryMock, + 'data' => [ + 'reserved_order_id' => 1000001 + ] ] ); } @@ -1237,4 +1240,30 @@ class QuoteTest extends \PHPUnit_Framework_TestCase $this->assertEquals($itemResult, $this->quote->getAllItems()); } + + /** + * Test to verify if existing reserved_order_id in use + * + * @param bool $isReservedOrderIdExist + * @param int $reservedOrderId + * @dataProvider reservedOrderIdDataProvider + */ + public function testReserveOrderId($isReservedOrderIdExist, $reservedOrderId) + { + $this->resourceMock + ->expects($this->once()) + ->method('isOrderIncrementIdUsed') + ->with(1000001)->willReturn($isReservedOrderIdExist); + $this->resourceMock->expects($this->any())->method('getReservedOrderId')->willReturn($reservedOrderId); + $this->quote->reserveOrderId(); + $this->assertEquals($reservedOrderId, $this->quote->getReservedOrderId()); + } + + public function reservedOrderIdDataProvider() + { + return [ + 'id_already_in_use' => [true, 100002], + 'id_not_in_use' => [false, 1000001] + ]; + } } diff --git a/app/code/Magento/Quote/Test/Unit/Model/ResourceModel/QuoteTest.php b/app/code/Magento/Quote/Test/Unit/Model/ResourceModel/QuoteTest.php new file mode 100644 index 0000000000000000000000000000000000000000..15c58073c2e26a4921f771e6c4097fafc9275c91 --- /dev/null +++ b/app/code/Magento/Quote/Test/Unit/Model/ResourceModel/QuoteTest.php @@ -0,0 +1,84 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Quote\Test\Unit\Model\ResourceModel; + +class QuoteTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Quote\Model\ResourceModel\Quote + */ + private $model; + + /** + * @var \Magento\Framework\App\ResourceConnection + */ + private $resourceMock; + + /** + * @var \Magento\Framework\DB\Adapter\Pdo\Mysql + */ + private $adapterMock; + + /** + * @var \Magento\Framework\DB\Select + */ + private $selectMock; + + protected function setUp() + { + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class) + ->disableOriginalConstructor() + ->getMock(); + $this->selectMock->expects($this->any())->method('from')->will($this->returnSelf()); + $this->selectMock->expects($this->any())->method('where'); + + $this->adapterMock = $this->getMockBuilder(\Magento\Framework\DB\Adapter\Pdo\Mysql::class) + ->disableOriginalConstructor() + ->getMock(); + $this->adapterMock->expects($this->any())->method('select')->will($this->returnValue($this->selectMock)); + + $this->resourceMock = $this->getMockBuilder(\Magento\Framework\App\ResourceConnection::class) + ->disableOriginalConstructor() + ->getMock(); + $this->resourceMock->expects( + $this->any() + )->method( + 'getConnection' + )->will( + $this->returnValue($this->adapterMock) + ); + + $this->model = $objectManagerHelper->getObject( + \Magento\Quote\Model\ResourceModel\Quote::class, + [ + 'resource' => $this->resourceMock + ] + ); + } + + /** + * Unit test to verify if isOrderIncrementIdUsed method works with different types increment ids + * + * @param array $value + * @dataProvider isOrderIncrementIdUsedDataProvider + */ + public function testIsOrderIncrementIdUsed($value) + { + $expectedBind = [':increment_id' => $value]; + $this->adapterMock->expects($this->once())->method('fetchOne')->with($this->selectMock, $expectedBind); + $this->model->isOrderIncrementIdUsed($value); + } + + /** + * @return array + */ + public function isOrderIncrementIdUsedDataProvider() + { + return [[100000001], ['10000000001'], ['M10000000001']]; + } +} diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js b/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js index be312c71f1fb20a1a2140765d598d8567bfaf648..b640b131aaf6fcb52ca883da80de65ab0cd75dd3 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js @@ -161,7 +161,6 @@ define([ defaultPlaceholder: $t('Select...'), lotPlaceholders: $t('Selected') }, - hoverElIndex: null, separator: 'optgroup', listens: { listVisible: 'cleanHoveredElement', @@ -295,7 +294,6 @@ define([ this._super(); this.observe([ 'listVisible', - 'hoverElIndex', 'placeholder', 'multiselectFocus', 'options', @@ -539,7 +537,7 @@ define([ }, /** - * Clean hoverElIndex variable + * Clean hoveredElement variable * * @returns {Object} Chainable */ diff --git a/app/code/Magento/Wishlist/Controller/Index/Cart.php b/app/code/Magento/Wishlist/Controller/Index/Cart.php index f15e89d16c9b4f9bba2adbe2a23621417e255f1a..a907abcd1c56c829dedaddbd065fff3cc1fede08 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Cart.php +++ b/app/code/Magento/Wishlist/Controller/Index/Cart.php @@ -113,6 +113,7 @@ class Cart extends \Magento\Wishlist\Controller\AbstractIndex * @return \Magento\Framework\Controller\ResultInterface * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function execute() { @@ -137,6 +138,10 @@ class Cart extends \Magento\Wishlist\Controller\AbstractIndex // Set qty $qty = $this->getRequest()->getParam('qty'); + $postQty = $this->getRequest()->getPostValue('qty'); + if ($postQty !== null && $qty !== $postQty) { + $qty = $postQty; + } if (is_array($qty)) { if (isset($qty[$itemId])) { $qty = $qty[$itemId]; diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php index e1a7cd448569f05060d9995ee5d02de41630f680..743fc39e4b43d7819af97fc97c84efb9f3f38013 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php @@ -159,7 +159,7 @@ class CartTest extends \PHPUnit_Framework_TestCase $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class) ->disableOriginalConstructor() - ->setMethods(['getParams', 'getParam', 'isAjax']) + ->setMethods(['getParams', 'getParam', 'isAjax', 'getPostValue']) ->getMockForAbstractClass(); $this->redirectMock = $this->getMockBuilder(\Magento\Framework\App\Response\RedirectInterface::class) @@ -916,4 +916,176 @@ class CartTest extends \PHPUnit_Framework_TestCase $this->assertSame($this->resultRedirectMock, $this->model->execute()); } + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testExecuteWithEditQuantity() + { + $itemId = 2; + $wishlistId = 1; + $qty = 1; + $postQty = 2; + $productId = 4; + $indexUrl = 'index_url'; + $configureUrl = 'configure_url'; + $options = [5 => 'option']; + $params = ['item' => $itemId, 'qty' => $qty]; + + $this->formKeyValidator->expects($this->once()) + ->method('validate') + ->with($this->requestMock) + ->willReturn(true); + + $itemMock = $this->getMockBuilder(\Magento\Wishlist\Model\Item::class) + ->disableOriginalConstructor() + ->setMethods( + [ + 'load', + 'getId', + 'getWishlistId', + 'setQty', + 'setOptions', + 'getBuyRequest', + 'mergeBuyRequest', + 'addToCart', + 'getProduct', + 'getProductId', + ] + ) + ->getMock(); + + $this->requestMock->expects($this->at(0)) + ->method('getParam') + ->with('item', null) + ->willReturn($itemId); + $this->itemFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($itemMock); + + $itemMock->expects($this->once()) + ->method('load') + ->with($itemId, null) + ->willReturnSelf(); + $itemMock->expects($this->exactly(2)) + ->method('getId') + ->willReturn($itemId); + $itemMock->expects($this->once()) + ->method('getWishlistId') + ->willReturn($wishlistId); + + $wishlistMock = $this->getMockBuilder(\Magento\Wishlist\Model\Wishlist::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->wishlistProviderMock->expects($this->once()) + ->method('getWishlist') + ->with($wishlistId) + ->willReturn($wishlistMock); + + $this->requestMock->expects($this->at(1)) + ->method('getParam') + ->with('qty', null) + ->willReturn($qty); + + $this->requestMock->expects($this->once()) + ->method('getPostValue') + ->with('qty') + ->willReturn($postQty); + + $this->quantityProcessorMock->expects($this->once()) + ->method('process') + ->with($postQty) + ->willReturnArgument(0); + + $itemMock->expects($this->once()) + ->method('setQty') + ->with($postQty) + ->willReturnSelf(); + + $this->urlMock->expects($this->at(0)) + ->method('getUrl') + ->with('*/*', null) + ->willReturn($indexUrl); + + $itemMock->expects($this->once()) + ->method('getProductId') + ->willReturn($productId); + + $this->urlMock->expects($this->at(1)) + ->method('getUrl') + ->with('*/*/configure/', ['id' => $itemId, 'product_id' => $productId]) + ->willReturn($configureUrl); + + $optionMock = $this->getMockBuilder(\Magento\Wishlist\Model\Item\Option::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->optionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($optionMock); + + $optionsMock = $this->getMockBuilder(\Magento\Wishlist\Model\ResourceModel\Item\Option\Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $optionMock->expects($this->once()) + ->method('getCollection') + ->willReturn($optionsMock); + + $optionsMock->expects($this->once()) + ->method('addItemFilter') + ->with([$itemId]) + ->willReturnSelf(); + $optionsMock->expects($this->once()) + ->method('getOptionsByItem') + ->with($itemId) + ->willReturn($options); + + $itemMock->expects($this->once()) + ->method('setOptions') + ->with($options) + ->willReturnSelf(); + + $this->requestMock->expects($this->once()) + ->method('getParams') + ->willReturn($params); + + $buyRequestMock = $this->getMockBuilder(\Magento\Framework\DataObject::class) + ->disableOriginalConstructor() + ->getMock(); + + $itemMock->expects($this->once()) + ->method('getBuyRequest') + ->willReturn($buyRequestMock); + + $this->productHelperMock->expects($this->once()) + ->method('addParamsToBuyRequest') + ->with($params, ['current_config' => $buyRequestMock]) + ->willReturn($buyRequestMock); + + $itemMock->expects($this->once()) + ->method('mergeBuyRequest') + ->with($buyRequestMock) + ->willReturnSelf(); + $itemMock->expects($this->once()) + ->method('addToCart') + ->with($this->checkoutCartMock, true) + ->willThrowException(new \Magento\Framework\Exception\LocalizedException(__('message'))); + + $this->messageManagerMock->expects($this->once()) + ->method('addNotice') + ->with('message', null) + ->willReturnSelf(); + + $this->helperMock->expects($this->once()) + ->method('calculate') + ->willReturnSelf(); + + $this->resultRedirectMock->expects($this->once()) + ->method('setUrl') + ->with($configureUrl) + ->willReturnSelf(); + + $this->assertSame($this->resultRedirectMock, $this->model->execute()); + } } diff --git a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml index dbb680f8f25806508e44ef31724899149ca2b6ce..b08816a6728eb54b79ec806084f4a4e684702a29 100644 --- a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml +++ b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml @@ -22,7 +22,7 @@ template="Magento_Catalog::product/view/addto.phtml" cacheable="false"> <block class="Magento\Wishlist\Block\Item\Configure" name="view.addto.wishlist.bundle" after="view.addto.requisition" template="item/configure/addto/wishlist.phtml" /> - <block class="Magento\Catalog\Block\Product\View\Addto\Compare" name="view.addto.compare.bundle" after="view.addto.wishlist" + <block class="Magento\Catalog\Block\Product\View\AddTo\Compare" name="view.addto.compare.bundle" after="view.addto.wishlist" template="Magento_Catalog::product/view/addto/compare.phtml" /> </block> </block> diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/CreateBundleProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/CreateBundleProductEntityTest.xml index 678e9306cbadb3bc22dafd9bca089a8b7f304ba7..211e09861995f27e22a446b93e465a7197936965 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/CreateBundleProductEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/CreateBundleProductEntityTest.xml @@ -195,8 +195,8 @@ <data name="product/data/price_type" xsi:type="string">Yes</data> <data name="product/data/price/dataset" xsi:type="string">dynamic-8</data> <data name="product/data/special_price" xsi:type="string">20</data> - <data name="product/data/special_from_date/pattern" xsi:type="string">M j, Y -1 day</data> - <data name="product/data/special_to_date/pattern" xsi:type="string">M j, Y +3 days</data> + <data name="product/data/special_from_date/pattern" xsi:type="string">m/d/y -1 day</data> + <data name="product/data/special_to_date/pattern" xsi:type="string">m/d/y +3 days</data> <data name="product/data/bundle_selections/dataset" xsi:type="string">default_dynamic</data> <data name="product/data/bundle_selections/products" xsi:type="string">catalogProductSimple::product_100_dollar,catalogProductSimple::product_40_dollar</data> <data name="product/data/checkout_data/dataset" xsi:type="string">bundle_default</data> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml index ecd68593b08cc252e67a144ccd2a9610ac88f22d..e1cbc1a1d8ba2dba7f3be971b3f1b456f6e7d02a 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml @@ -1233,5 +1233,35 @@ <field name="url_key" xsi:type="string">overnight-duffle</field> </dataset> + <dataset name="simple_with_weight_10_for_salesrule"> + <field name="attribute_set_id" xsi:type="array"> + <item name="dataset" xsi:type="string">default</item> + </field> + <field name="name" xsi:type="string">Simple Product %isolation%</field> + <field name="sku" xsi:type="string">sku_simple_product_%isolation%</field> + <field name="product_has_weight" xsi:type="string">This item has weight</field> + <field name="weight" xsi:type="string">10</field> + <field name="quantity_and_stock_status" xsi:type="array"> + <item name="qty" xsi:type="string">25</item> + <item name="is_in_stock" xsi:type="string">In Stock</item> + </field> + <field name="price" xsi:type="array"> + <item name="value" xsi:type="string">560</item> + </field> + <field name="tax_class_id" xsi:type="array"> + <item name="dataset" xsi:type="string">taxable_goods</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="visibility" xsi:type="string">Catalog, Search</field> + <field name="url_key" xsi:type="string">simple-product-%isolation%</field> + <field name="checkout_data" xsi:type="array"> + <item name="dataset" xsi:type="string">simple_order_default</item> + </field> + </dataset> + </repository> </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 697733fd3c33d8856f5d775452aca8ad977e77e9..fac0f811be2616675e85e3f34927731f13ea16b1 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 @@ -99,6 +99,13 @@ class Cart extends Block */ protected $preloaderSpinner = '#preloaderSpinner'; + /** + * Cart item class name. + * + * @var string + */ + protected $cartItemClass = \Magento\Checkout\Test\Block\Cart\CartItem::class; + /** * Wait for PayPal page is loaded. * @@ -129,7 +136,7 @@ class Cart extends Block Locator::SELECTOR_XPATH ); $cartItem = $this->blockFactory->create( - '\\' . get_class($this) . '\CartItem', + $this->cartItemClass, ['element' => $cartItemBlock] ); } diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php index a3eda5ea1b3c5a3d6b5be217df906ca69b67f742..d29bad980faca881468ae1cf3a58523e13f7ad83 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php @@ -13,5 +13,13 @@ use Magento\Mtf\Block\Form; */ class Shipping extends Form { - // + /** + * Returns form's required elements + * + * @return \Magento\Mtf\Client\ElementInterface[] + */ + public function getRequiredFields() + { + return $this->_rootElement->getElements("div .field._required"); + } } diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertShippingAddressJsValidationMessagesIsAbsent.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertShippingAddressJsValidationMessagesIsAbsent.php new file mode 100644 index 0000000000000000000000000000000000000000..f4f46a1c2b7c2577a0f61882f9d707397b1c1a20 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertShippingAddressJsValidationMessagesIsAbsent.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Test\Constraint; + +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Class AssertShippingAddressJsValidationMessagesIsAbsent + * Assert js validation messages are absent for required fields. + */ +class AssertShippingAddressJsValidationMessagesIsAbsent extends AbstractConstraint +{ + /** + * Assert js validation messages are absent for required fields. + * + * @param CheckoutOnepage $checkoutOnepage + * @return void + */ + public function processAssert(CheckoutOnepage $checkoutOnepage) + { + $requiredFields = $checkoutOnepage->getShippingBlock()->getRequiredFields(); + + /** @var \Magento\Mtf\Client\ElementInterface $field */ + foreach ($requiredFields as $field) { + $errorContainer = $field->find("div .field-error"); + \PHPUnit_Framework_Assert::assertFalse( + $errorContainer->isVisible(), + 'Js validation error messages must be absent for required fields after checkout start.' + ); + } + } + + /** + * Returns string representation of successful assertion + * + * @return string + */ + public function toString() + { + return 'Js validation messages are absent for required fields.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5361ee6e3c127bafc03e53cd717ac067688f826a --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Steps: + * 1. Go to Frontend as guest. + * 2. Add simple product to shopping cart + * 3. Go to shopping cart page + * 4. Proceed to checkout + * 5. Perform assertions. + * + * @group One_Page_Checkout + * @ZephyrId MAGETWO-59697 + */ +class OnePageCheckoutJsValidationTest extends Scenario +{ + /** + * Runs one page checkout js validation test. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..e930ff29882ceed4e8f99947a6a6ef4b4acc1c7a --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.xml @@ -0,0 +1,16 @@ +<?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\Checkout\Test\TestCase\OnePageCheckoutJsValidationTest" summary="JS validation verification for Checkout flow" ticketId="MAGETWO-59697"> + <variation name="OnePageCheckoutJsValidationTestVariation1" summary="JS validation is not applied for empty required checkout fields if customer did not fill them"> + <data name="products/0" xsi:type="string">catalogProductSimple::default</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <constraint name="Magento\Checkout\Test\Constraint\AssertShippingAddressJsValidationMessagesIsAbsent" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml index a26a2cead49b07a094e550db1207e36d53269b15..24eb96c0a9347741384ffd6718bf349eeb452c85 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml @@ -22,4 +22,10 @@ <step name="placeOrder" module="Magento_Checkout" next="createCustomerAccount" /> <step name="createCustomerAccount" module="Magento_Checkout" /> </scenario> + <scenario name="OnePageCheckoutJsValidationTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> + <step name="createProducts" module="Magento_Catalog" next="addProductsToTheCart" /> + <step name="addProductsToTheCart" module="Magento_Checkout" next="ProceedToCheckout" /> + <step name="ProceedToCheckout" module="Magento_Checkout" /> + </scenario> </config> diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php index 5ab10a0e26f79fcded0b42c77562b077cf0b5412..310f52f75e2cf124e07ab1d7d4bf431e48759e8d 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php @@ -70,6 +70,10 @@ class Curl extends Conditions implements SalesRuleInterface 'type' => \Magento\SalesRule\Model\Rule\Condition\Address::class, 'attribute' => 'postcode', ], + 'Total Weight' => [ + 'type' => \Magento\SalesRule\Model\Rule\Condition\Address::class, + 'attribute' => 'weight', + ], 'Category' => [ 'type' => \Magento\SalesRule\Model\Rule\Condition\Product::class, 'attribute' => 'category_ids', diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml index 010b9d3233d163f6ec35ed4291bebbe352bbe9c4..13b68aca6c6eb7867286019b3a9609b3b93db2a8 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml @@ -279,5 +279,24 @@ <field name="stop_rules_processing" xsi:type="string">No</field> <field name="simple_free_shipping" xsi:type="string">No</field> </dataset> + <dataset name="rule_with_freeshipping_by_weight"> + <field name="name" xsi:type="string">Cart price rule with free shipping by weight</field> + <field name="is_active" xsi:type="string">Yes</field> + <field name="website_ids" xsi:type="array"> + <item name="0" xsi:type="string">Main Website</item> + </field> + <field name="customer_group_ids" xsi:type="array"> + <item name="0" xsi:type="string">NOT LOGGED IN</item> + </field> + <field name="coupon_type" xsi:type="string">No Coupon</field> + <field name="sort_order" xsi:type="string">1</field> + <field name="is_rss" xsi:type="string">Yes</field> + <field name="conditions_serialized" xsi:type="string">[Total Weight|is|1]</field> + <field name="simple_action" xsi:type="string">Percent of product price discount</field> + <field name="discount_amount" xsi:type="string">0</field> + <field name="apply_to_shipping" xsi:type="string">No</field> + <field name="stop_rules_processing" xsi:type="string">No</field> + <field name="simple_free_shipping" xsi:type="string">For matching items only</field> + </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ShoppingCartWithFreeShippingTest.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ShoppingCartWithFreeShippingTest.php new file mode 100644 index 0000000000000000000000000000000000000000..11e510759fdcc5aa4c9368e61c3f5373d32dd9bb --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ShoppingCartWithFreeShippingTest.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\SalesRule\Test\TestCase; + +/** + * Precondition: + * 1. Cart Price Rule was created. + * + * Steps: + * 1. Go to storefront + * 2. Add product to shopping cart + * 3. Go to shopping cart page + * 4. Perform asserts. + * + * @group Shopping_Cart_Price_Rules + * @ZephyrId MAGETWO-59665 + */ +class ShoppingCartWithFreeShippingTest extends \Magento\Mtf\TestCase\Injectable +{ + /** + * @var \Magento\Mtf\TestStep\TestStepFactory + */ + private $testStepFactory; + + /** + * Inject data + * + * @param \Magento\Mtf\TestStep\TestStepFactory $testStepFactory + * @return void + */ + public function __inject( + \Magento\Mtf\TestStep\TestStepFactory $testStepFactory + ) { + $this->testStepFactory = $testStepFactory; + } + + /** + * Test sales rule with free shipping applied by product weight + * + * @param \Magento\SalesRule\Test\Fixture\SalesRule $salesRule + * @param \Magento\Catalog\Test\Fixture\CatalogProductSimple $product + * @param \Magento\Checkout\Test\Fixture\Cart $cart + * @return void + */ + public function testRuleWithFreeShippingByWeight( + \Magento\SalesRule\Test\Fixture\SalesRule $salesRule, + \Magento\Catalog\Test\Fixture\CatalogProductSimple $product, + \Magento\Checkout\Test\Fixture\Cart $cart + ) { + $salesRule->persist(); + $product->persist(); + + $this->testStepFactory->create( + \Magento\Checkout\Test\TestStep\AddProductsToTheCartStep::class, + ['products' => [$product]] + )->run(); + + $this->testStepFactory->create( + \Magento\Checkout\Test\TestStep\EstimateShippingAndTaxStep::class, + ['products' => [$product], 'cart' => $cart] + )->run(); + } + + /** + * Clear data after test. + * + * @return void + */ + public function tearDown() + { + $this->testStepFactory->create(\Magento\SalesRule\Test\TestStep\DeleteAllSalesRuleStep::class)->run(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ShoppingCartWithFreeShippingTest.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ShoppingCartWithFreeShippingTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..7391d2281f8094b059cfaf9d26115c371d9498b0 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ShoppingCartWithFreeShippingTest.xml @@ -0,0 +1,25 @@ +<?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\SalesRule\Test\TestCase\ShoppingCartWithFreeShippingTest" summary="Shopping Cart With Freeshipping" ticketId="MAGETWO-59665"> + <variation name="ShoppingCartWithFreeShippingTestVariation1"> + <data name="salesRule/dataset" xsi:type="string">rule_with_freeshipping_by_weight</data> + <data name="product/dataset" xsi:type="string">default</data> + <data name="cart/data/subtotal" xsi:type="string">560.00</data> + <data name="cart/data/shipping_amount" xsi:type="string">0.00</data> + <data name="cart/data/grand_total" xsi:type="string">560.00</data> + </variation> + <variation name="ShoppingCartWithFreeShippingTestVariation2"> + <data name="salesRule/dataset" xsi:type="string">rule_with_freeshipping_by_weight</data> + <data name="product/dataset" xsi:type="string">simple_with_weight_10_for_salesrule</data> + <data name="cart/data/subtotal" xsi:type="string">560.00</data> + <data name="cart/data/shipping_amount" xsi:type="string">5.00</data> + <data name="cart/data/grand_total" xsi:type="string">565.00</data> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Customer/Wishlist.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Customer/Wishlist.php index 47f787da38b04264372015a52449f984820490e5..bda0780f553006bddc3f0ce164cb4f6f824ee75d 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Customer/Wishlist.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Customer/Wishlist.php @@ -99,6 +99,7 @@ class Wishlist extends Block public function clickUpdateWishlist() { $this->waitFormToLoad(); + $this->_rootElement->hover(); $this->_rootElement->find($this->updateButton)->click(); } diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Api/StockItemSaveTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Api/StockItemSaveTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0dc5c3ef620c3c307d4b35b6b7b0e61091128775 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Api/StockItemSaveTest.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogInventory\Api; + +use Magento\Catalog\Api\Data\ProductExtensionInterface; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; + +class StockItemSaveTest extends \PHPUnit_Framework_TestCase +{ + /** + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + */ + public function testSave() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = $objectManager->get(ProductRepositoryInterface::class); + /** @var ProductInterface $product */ + $product = $productRepository->get('simple', false, null, true); + + /** @var ProductExtensionInterface $ea */ + $ea = $product->getExtensionAttributes(); + $ea->getStockItem()->setQty(555); + $productRepository->save($product); + + $product = $productRepository->get('simple', false, null, true); + $this->assertEquals(555, $product->getExtensionAttributes()->getStockItem()->getQty()); + + $stockItem = $product->getExtensionAttributes()->getStockItem(); + $stockItem->setQty(200); + /** @var StockItemRepositoryInterface $stockItemRepository */ + $stockItemRepository = $objectManager->get(StockItemRepositoryInterface::class); + $stockItemRepository->save($stockItem); + $this->assertEquals(200, $product->getExtensionAttributes()->getStockItem()->getQty()); + + $product = $productRepository->get('simple', false, null, true); + $this->assertEquals(200, $product->getExtensionAttributes()->getStockItem()->getQty()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..50787c7962412b0611edf093825563061da67119 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\ConfigurableProduct\Pricing\Price; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; + +class LowestPriceOptionProviderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var LowestPriceOptionsProviderInterface + */ + private $lowestPriceOptionsProvider; + + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + protected function setUp() + { + $this->storeManager = Bootstrap::getObjectManager()->get(StoreManagerInterface::class); + $this->productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); + $this->lowestPriceOptionsProvider = Bootstrap::getObjectManager()->get( + LowestPriceOptionsProviderInterface::class + ); + } + + /** + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ + public function testGetProductsIfOneOfChildIsDisabled() + { + $configurableProduct = $this->productRepository->getById(1, false, null, true); + $lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct); + $this->assertCount(1, $lowestPriceChildrenProducts); + $lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts); + $this->assertEquals(10, $lowestPriceChildrenProduct->getPrice()); + + // load full aggregation root + $lowestPriceChildProduct = $this->productRepository->get( + $lowestPriceChildrenProduct->getSku(), + false, + null, + true + ); + $lowestPriceChildProduct->setStatus(Status::STATUS_DISABLED); + // update in global scope + $currentStoreId = $this->storeManager->getStore()->getId(); + $this->storeManager->setCurrentStore(Store::ADMIN_CODE); + $this->productRepository->save($lowestPriceChildProduct); + $this->storeManager->setCurrentStore($currentStoreId); + + $lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct); + $this->assertCount(1, $lowestPriceChildrenProducts); + $lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts); + $this->assertEquals(20, $lowestPriceChildrenProduct->getPrice()); + } + + /** + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ + public function testGetProductsIfOneOfChildIsOutOfStock() + { + $configurableProduct = $this->productRepository->getById(1, false, null, true); + $lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct); + $this->assertCount(1, $lowestPriceChildrenProducts); + $lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts); + $this->assertEquals(10, $lowestPriceChildrenProduct->getPrice()); + + // load full aggregation root + $lowestPriceChildProduct = $this->productRepository->get( + $lowestPriceChildrenProduct->getSku(), + false, + null, + true + ); + $stockItem = $lowestPriceChildProduct->getExtensionAttributes()->getStockItem(); + $stockItem->setIsInStock(0); + $this->productRepository->save($lowestPriceChildProduct); + + $lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct); + $this->assertCount(1, $lowestPriceChildrenProducts); + $lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts); + $this->assertEquals(20, $lowestPriceChildrenProduct->getPrice()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/LayoutDirectivesTest.php b/dev/tests/integration/testsuite/Magento/Framework/View/LayoutDirectivesTest.php index 7a20762bbe9d4493131bb0f2acb8e432a0a9ddbf..607ee4c919a62437cdfaf0d2219248dfc77f7a27 100755 --- a/dev/tests/integration/testsuite/Magento/Framework/View/LayoutDirectivesTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/View/LayoutDirectivesTest.php @@ -198,6 +198,18 @@ class LayoutDirectivesTest extends \PHPUnit_Framework_TestCase $this->assertTrue($layout->isBlock('child_block2')); } + /** + * @magentoAppIsolation enabled + */ + public function testRemoveCancellation() + { + $layout = $this->_getLayoutModel('remove_cancellation.xml'); + $this->assertTrue($layout->isContainer('container1')); + $this->assertTrue($layout->isBlock('child_block1')); + $this->assertTrue($layout->isBlock('no_name2')); + $this->assertFalse($layout->getBlock('not_exist')); + } + /** * @magentoAppIsolation enabled */ diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/layout_directives_test/remove_cancellation.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/layout_directives_test/remove_cancellation.xml new file mode 100644 index 0000000000000000000000000000000000000000..ff086b19fd1b02d80ffc849d9563bdb9419ae75e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/layout_directives_test/remove_cancellation.xml @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<layout> + <container name="container1" label="Container 1"> + <block class="Magento\Framework\View\Element\Text" name="no_name2"/> + </container> + <referenceContainer name="container1" remove="true"/> + <referenceBlock name="child_block1" remove="true"/> + <block class="Magento\Framework\View\Element\Text" name="block_container" as="block.container"> + <block class="Magento\Framework\View\Element\Text" name="child_block1"/> + <block class="Magento\Framework\View\Element\Text" name="child_block2"/> + </block> + <referenceContainer name="not_exist" remove="false"/> + <referenceContainer name="container1" remove="false"/> + <referenceBlock name="child_block1" remove="false"/> +</layout> diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php index da035c8eec78f8a547defd548f5cc93b10d474a6..8f295077afe330076e265c555cae280294cdd9f6 100644 --- a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php @@ -404,4 +404,23 @@ class QuoteTest extends \PHPUnit_Framework_TestCase \Magento\Customer\Model\Data\Customer::WEBSITE_ID => 1 ]; } + + /** + * Test to verify that reserved_order_id will be changed if it already in used + * + * @magentoDataFixture Magento/Sales/_files/order.php + * @magentoDataFixture Magento/Quote/_files/empty_quote.php + */ + public function testReserveOrderId() + { + $objectManager = Bootstrap::getObjectManager(); + /** @var \Magento\Quote\Model\Quote $quote */ + $quote = $objectManager->create(\Magento\Quote\Model\Quote::class); + $quote->load('reserved_order_id', 'reserved_order_id'); + $quote->reserveOrderId(); + $this->assertEquals('reserved_order_id', $quote->getReservedOrderId()); + $quote->setReservedOrderId('100000001'); + $quote->reserveOrderId(); + $this->assertNotEquals('100000001', $quote->getReservedOrderId()); + } } diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/ResourceModel/QuoteTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/ResourceModel/QuoteTest.php new file mode 100644 index 0000000000000000000000000000000000000000..43ee0893b75f9cc93bdca626d87d5592eefd62aa --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/ResourceModel/QuoteTest.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Quote\Model\ResourceModel; + +/** + * Class QuoteTest to verify isOrderIncrementIdUsed method behaviour + */ +class QuoteTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Quote\Model\ResourceModel\Quote + */ + private $_resourceModel; + + protected function setUp() + { + $this->_resourceModel = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Quote\Model\ResourceModel\Quote::class + ); + } + + /** + * Test to verify if isOrderIncrementIdUsed method works with numeric increment ids + * + * @magentoDataFixture Magento/Sales/_files/order.php + */ + public function testIsOrderIncrementIdUsedNumericIncrementId() + { + $this->assertTrue($this->_resourceModel->isOrderIncrementIdUsed('100000001')); + } + + /** + * Test to verify if isOrderIncrementIdUsed method works with alphanumeric increment ids + * + * @magentoDataFixture Magento/Sales/_files/order_alphanumeric_id.php + */ + public function testIsOrderIncrementIdUsedAlphanumericIncrementId() + { + $this->assertTrue($this->_resourceModel->isOrderIncrementIdUsed('M00000001')); + } +} diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/Model/Quote/Address/Total/ShippingTest.php b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Quote/Address/Total/ShippingTest.php new file mode 100644 index 0000000000000000000000000000000000000000..543d02e42067483a56ee1b31d084a7e02c18952f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Quote/Address/Total/ShippingTest.php @@ -0,0 +1,106 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\SalesRule\Model\Quote\Address\Total; + +class ShippingTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Quote\Api\GuestCartManagementInterface + */ + private $cartManagement; + + /** + * @var \Magento\Quote\Api\GuestCartItemRepositoryInterface + */ + private $itemRepository; + + /** + * @var \Magento\Framework\ObjectManagerInterface + */ + private $objectManager; + + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->cartManagement = $this->objectManager->get(\Magento\Quote\Api\GuestCartManagementInterface::class); + $this->itemRepository = $this->objectManager->get(\Magento\Quote\Api\GuestCartItemRepositoryInterface::class); + } + + /** + * @magentoDataFixture Magento/SalesRule/_files/rule_free_shipping_by_product_weight.php + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + */ + public function testRuleByProductWeightWithFreeShipping() + { + $cartId = $this->prepareQuote(1); + $methods = $this->estimateShipping($cartId); + + $this->assertTrue(count($methods) > 0); + $this->assertEquals('flatrate', $methods[0]->getMethodCode()); + $this->assertEquals(0, $methods[0]->getAmount()); + + } + + /** + * @magentoDataFixture Magento/SalesRule/_files/rule_free_shipping_by_product_weight.php + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + */ + public function testRuleByProductWeightWithoutFreeShipping() + { + $cartId = $this->prepareQuote(5); + $methods = $this->estimateShipping($cartId); + + $this->assertTrue(count($methods) > 0); + $this->assertEquals('flatrate', $methods[0]->getMethodCode()); + $this->assertEquals(25, $methods[0]->getAmount()); + + } + + /** + * Estimate shipment for guest cart + * + * @param int $cartId + * @return \Magento\Quote\Api\Data\ShippingMethodInterface[] + */ + private function estimateShipping($cartId) + { + $addressFactory = $this->objectManager->get(\Magento\Quote\Api\Data\AddressInterfaceFactory::class); + /** @var \Magento\Quote\Api\Data\AddressInterface $address */ + $address = $addressFactory->create(); + $address->setCountryId('US'); + $address->setRegionId(2); + + /** @var \Magento\Quote\Api\GuestShipmentEstimationInterface $estimation */ + $estimation = $this->objectManager->get(\Magento\Quote\Api\GuestShipmentEstimationInterface::class); + return $estimation->estimateByExtendedAddress($cartId, $address); + } + + /** + * Create guest quote with products + * + * @param int $itemQty + * @return int + */ + private function prepareQuote($itemQty) + { + $cartId = $this->cartManagement->createEmptyCart(); + + /** @var \Magento\Quote\Api\Data\CartItemInterfaceFactory $cartItemFactory */ + $cartItemFactory = $this->objectManager->get(\Magento\Quote\Api\Data\CartItemInterfaceFactory::class); + + /** @var \Magento\Quote\Api\Data\CartItemInterface $cartItem */ + $cartItem = $cartItemFactory->create(); + $cartItem->setQuoteId($cartId); + $cartItem->setQty($itemQty); + $cartItem->setSku('simple'); + $cartItem->setProductType(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE); + + $this->itemRepository->save($cartItem); + + return $cartId; + } +} diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/rule_free_shipping_by_product_weight.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/rule_free_shipping_by_product_weight.php new file mode 100644 index 0000000000000000000000000000000000000000..d59f63d2f313601b06bafdac7287501980e20b37 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/rule_free_shipping_by_product_weight.php @@ -0,0 +1,35 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +require 'cart_rule_free_shipping.php'; +$row = + [ + 'name' => 'Free shipping if item weight <= 1', + 'conditions' => [ + 1 => + [ + 'type' => \Magento\SalesRule\Model\Rule\Condition\Combine::class, + 'attribute' => null, + 'operator' => null, + 'value' => '1', + 'is_value_processed' => null, + 'aggregator' => 'all', + 'conditions' => [ + [ + 'type' => Magento\SalesRule\Model\Rule\Condition\Address::class, + 'attribute' => 'weight', + 'operator' => '<=', + 'value' => '1', + 'is_value_processed' => false, + ] + ] + ] + + ], + 'actions' => [], + ]; +$salesRule->loadPost($row); +$salesRule->save(); diff --git a/dev/tests/js/jasmine/spec_runner/tasks/jasmine.js b/dev/tests/js/jasmine/spec_runner/tasks/jasmine.js index 5d520860f44105371984c918ddd643f1f05c1611..ccd21fafe33b9220f3203bf4fa0697ad2abc2d2f 100644 --- a/dev/tests/js/jasmine/spec_runner/tasks/jasmine.js +++ b/dev/tests/js/jasmine/spec_runner/tasks/jasmine.js @@ -37,6 +37,10 @@ function init(config) { host: host, template: render(files.template), vendor: files.requireJs, + junit: { + path: "var/log/js-unit/", + consolidate: true + }, /** * @todo rename "helpers" to "specs" (implies overriding grunt-contrib-jasmine code) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js index 806964352be5f23ea088d91b683400d00020c342..6fbbc63af473c36baa9f5c7fdf55d2e0fa6b907c 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js @@ -21,38 +21,6 @@ define([ index: '' }); - registry.set('provName', { - on: function () { - }, - get: function () { - }, - set: function () { - } - }); - - describe('"initProperties" method', function () { - it('Check for defined ', function () { - expect(obj.hasOwnProperty('initProperties')).toBeDefined(); - }); - it('Check answer type', function () { - var type = typeof obj.initProperties; - - expect(type).toEqual('function'); - }); - it('Check returned value if method called without arguments', function () { - expect(obj.initProperties()).toBeDefined(); - }); - it('Check returned value type if method called without arguments', function () { - var type = typeof obj.initProperties(); - - expect(type).toEqual('object'); - }); - it('Check "displayed" property', function () { - obj.displayed = null; - obj.initProperties(); - expect(obj.displayed).toEqual([]); - }); - }); describe('"initObservable" method', function () { it('Check for defined ', function () { expect(obj.hasOwnProperty('initObservable')).toBeDefined(); @@ -178,16 +146,23 @@ define([ prefix: 'magento' }; + obj.getPreview = jasmine.createSpy().and.callFake(function () { + return []; + }); + expect(obj.buildPreview(arg)).toBeDefined(); }); it('Check returned value type if method called with object argument', function () { var arg = { items: [], prefix: 'magento' - }, - type = typeof obj.buildPreview(arg); + }; + + obj.getPreview = jasmine.createSpy().and.callFake(function () { + return []; + }); - expect(type).toEqual('string'); + expect(typeof obj.buildPreview(arg)).toEqual('string'); }); it('Check called "this.getPreview" method with object argument', function () { var arg = { diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab.test.js index 56449c04406a08f0a8a5bc021726322ecd13bd59..10c9e5d35daeddeb16fa89b928f357b7770bdd66 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab.test.js @@ -56,23 +56,6 @@ define([ expect(obj.observe).toHaveBeenCalled(); }); }); - describe('"onUniqueUpdate" method', function () { - it('Check for defined ', function () { - expect(obj.hasOwnProperty('onUniqueUpdate')).toBeDefined(); - }); - it('Check method type', function () { - var type = typeof obj.onUniqueUpdate; - - expect(type).toEqual('function'); - }); - it('Check called "this.trigger" inner onUniqueUpdate method', function () { - obj.trigger = jasmine.createSpy().and.callFake(function () { - return obj; - }); - obj.onUniqueUpdate(); - expect(obj.trigger).toHaveBeenCalled(); - }); - }); describe('"activate" method', function () { it('Check for defined ', function () { expect(obj.hasOwnProperty('activate')).toBeDefined(); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab_group.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab_group.test.js index 173e803b14a2151df665ebd97bd145cf374f26ee..311b023a003a85fba8f8d4a7beb89f8cb65dce04 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab_group.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab_group.test.js @@ -23,14 +23,6 @@ define([ }); window.FORM_KEY = 'magentoFormKey'; - registry.set('provName', { - on: function () { - }, - get: function () { - }, - set: function () { - } - }); describe('"initElement" method', function () { it('Check for defined ', function () { @@ -48,6 +40,8 @@ define([ on: function () { }, active: function () { + }, + activate: function () { } }; @@ -60,6 +54,8 @@ define([ on: function () { }, active: function () { + }, + activate: function () { } }, type = typeof obj.initElement(arg); @@ -83,6 +79,8 @@ define([ on: function () { }, active: function () { + }, + activate: function () { } }; @@ -95,6 +93,8 @@ define([ on: function () { }, active: function () { + }, + activate: function () { } }, type = typeof obj.initActivation(arg); @@ -119,6 +119,8 @@ define([ }, active: function () { }, + activate: function () { + }, delegate: jasmine.createSpy() }; @@ -150,7 +152,7 @@ define([ return []; }); obj.onValidate(); - expect(obj.validate.calls.count()).toBe(3); + expect(obj.validate.calls.count()).toBe(1); }); }); }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/abstract.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/abstract.test.js index 0923d84fce5ff0e39149219a2ba951dcc1b6ebf9..7730bc72f7af6e35ffea47a4e2c6831328672dcc 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/abstract.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/abstract.test.js @@ -43,17 +43,6 @@ define([ expect(model.validation).toEqual({}); }); }); - describe('initProperties method', function () { - it('check for chainable', function () { - expect(model.initProperties()).toEqual(model); - }); - it('check for extend', function () { - model.initProperties(); - expect(model.uid).toBeDefined(); - expect(model.noticeId).toBeDefined(); - expect(model.inputName).toBeDefined(); - }); - }); describe('setInitialValue method', function () { it('check for chainable', function () { expect(model.setInitialValue()).toEqual(model); @@ -78,15 +67,23 @@ define([ expect(model.additionalClasses).toEqual(1); }); it('check for empty additional class', function () { + var expectedResult = { + _required: model.required, + _warn: model.warn, + _error: model.error, + _disabled: model.disabled + }; + model.additionalClasses = ''; expect(model._setClasses()).toEqual(model); - expect(model.additionalClasses).toEqual(''); + expect(model.additionalClasses).toEqual(expectedResult); }); it('check for one class in additional', function () { var extendObject = { simple: true, - required: model.required, + _required: model.required, + _warn: model.warn, _error: model.error, _disabled: model.disabled }; @@ -98,7 +95,8 @@ define([ it('check for one class with spaces in additional', function () { var extendObject = { simple: true, - required: model.required, + _required: model.required, + _warn: model.warn, _error: model.error, _disabled: model.disabled }; @@ -111,7 +109,8 @@ define([ var extendObject = { simple: true, example: true, - required: model.required, + _required: model.required, + _warn: model.warn, _error: model.error, _disabled: model.disabled }; @@ -124,7 +123,8 @@ define([ var extendObject = { simple: true, example: true, - required: model.required, + _required: model.required, + _warn: model.warn, _error: model.error, _disabled: model.disabled }; @@ -139,10 +139,8 @@ define([ expect(model.getInitialValue()).toEqual(''); }); it('check with default value', function () { - var expected = 1; - - model.default = expected; - expect(model.getInitialValue()).toEqual(expected); + model.default = 1; + expect(model.getInitialValue()).toEqual(''); }); it('check with value', function () { var expected = 1; diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js index 632fef3d841d1becdc65ff4e8ddfdcc553a3557f..de6b83eaf2005d06c324c3b7da997b541d305522 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js @@ -19,33 +19,5 @@ define([ }; model = new DateElement(params); }); - - describe('getInitialValue method', function () { - it('check for default', function () { - expect(model.getInitialValue()).toEqual(''); - }); - it('check with default value', function () { - model.default = 1; - expect(model.getInitialValue()).toEqual('01/01/1970'); - }); - it('check with value', function () { - model.value(1); - expect(model.getInitialValue()).toEqual('01/01/1970'); - }); - it('check with value and default', function () { - model.default = 1; - model.value(0); - expect(model.getInitialValue()).toEqual(0); - }); - }); - describe('initProperties method', function () { - it('check for chainable', function () { - expect(model.initProperties()).toEqual(model); - }); - it('check for extend', function () { - model.initProperties(); - expect(model.dateFormat).toBeDefined(); - }); - }); }); }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/multiselect.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/multiselect.test.js deleted file mode 100644 index 09f21f6b175ee21661cc8138ae319fc9be98bd14..0000000000000000000000000000000000000000 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/multiselect.test.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -/*eslint max-nested-callbacks: 0*/ - -define([ - 'Magento_Ui/js/form/element/multiselect' -], function (MultiselectElement) { - 'use strict'; - - describe('Magento_Ui/js/form/element/multiselect', function () { - var params, model; - - beforeEach(function () { - params = { - dataScope: 'multiselect' - }; - model = new MultiselectElement(params); - }); - - describe('getInitialValue method', function () { - it('check for default', function () { - expect(model.getInitialValue()).toEqual(undefined); - }); - it('check with default value', function () { - model.indexedOptions = { - Select: { - value: 'value' - } - }; - model.default = 'Select'; - expect(model.getInitialValue()).toEqual(['value']); - }); - it('check with value', function () { - model.indexedOptions = { - Select: { - value: 'value' - } - }; - model.value('Select'); - expect(model.getInitialValue()).toEqual(['value']); - }); - }); - }); -}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js index 6ce3428a6cb35f4a15063de0ba26e3612e1605d2..db5855b0a692bb7ac0c9b75de35d228abe309016 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js @@ -52,64 +52,6 @@ define([ it('check for chainable', function () { expect(model.initConfig({})).toEqual(model); }); - it('check with empty value and caption', function () { - var config = { - options: [{ - label: 'Caption', - value: null - }, { - label: 'Some label', - value: 'Some value' - }], - caption: 'Main caption' - }, - expected = { - options: [config.options[1]], - caption: config.caption - }; - - expect(model.initConfig(config)).toEqual(model); - expect(config).toEqual(expected); - }); - it('check with empty value', function () { - var config = { - options: [{ - label: 'Caption', - value: null - }, { - label: 'Some label', - value: 'Some value' - }] - }, - expected = { - options: [config.options[1]], - caption: config.options[0].label - }; - - expect(model.initConfig(config)).toEqual(model); - expect(config).toEqual(expected); - }); - it('check with multiple empty value', function () { - var config = { - options: [{ - label: 'Caption', - value: null - }, { - label: 'Some label', - value: 'Some value' - }, { - label: 'Another caption', - value: null - }] - }, - expected = { - options: [config.options[1]], - caption: config.options[0].label - }; - - expect(model.initConfig(config)).toEqual(model); - expect(config).toEqual(expected); - }); }); describe('initObservable method', function () { it('check for chainable', function () { diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/form.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/form.test.js index 5a32d5c991e3e06b50647c03057a3cc19ac1239f..88203afba331333193482a79c3e061202e93a2b4 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/form.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/form.test.js @@ -67,26 +67,26 @@ define([ expect(type).toEqual('object'); }); }); - describe('"initProperties" method', function () { + describe('"initConfig" method', function () { it('Check for defined ', function () { - expect(obj.hasOwnProperty('initProperties')).toBeDefined(); + expect(obj.hasOwnProperty('initConfig')).toBeDefined(); }); it('Check method type', function () { - var type = typeof obj.initProperties; + var type = typeof obj.initConfig; expect(type).toEqual('function'); }); it('Check returned value if method called without arguments', function () { - expect(obj.initProperties()).toBeDefined(); + expect(obj.initConfig()).toBeDefined(); }); it('Check returned value type if method called without arguments', function () { - var type = typeof obj.initProperties(); + var type = typeof obj.initConfig(); expect(type).toEqual('object'); }); - it('Check this.selector property (is modify in initProperties method)', function () { + it('Check this.selector property (is modify in initConfig method)', function () { obj.selector = null; - obj.initProperties(); + obj.initConfig(); expect(typeof obj.selector).toEqual('string'); }); }); @@ -117,33 +117,6 @@ define([ expect(type).toEqual('function'); }); - it('Check call method "this.validate" inner save method', function () { - obj.validate = jasmine.createSpy(); - obj.source.get = jasmine.createSpy().and.callFake(function () { - return true; - }); - obj.save(); - expect(obj.validate).toHaveBeenCalled(); - }); - it('Check call method "this.source.get" inner save method', function () { - obj.validate = jasmine.createSpy(); - obj.source.get = jasmine.createSpy().and.callFake(function () { - return true; - }); - obj.save(); - expect(obj.source.get).toHaveBeenCalled(); - }); - it('Check call method "this.submit" inner save method', function () { - obj.validate = jasmine.createSpy(); - obj.source.get = jasmine.createSpy().and.callFake(function () { - return false; - }); - obj.submit = jasmine.createSpy().and.callFake(function () { - return true; - }); - obj.save(); - expect(obj.source.get).toHaveBeenCalled(); - }); }); describe('"submit" method', function () { it('Check for defined ', function () { diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/ui-select.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/ui-select.test.js index 6a646c7c709099b917a08df1f3f795cce262dca0..5ffa5792b0882385c26546d6fbd834f3dde68a03 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/ui-select.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/ui-select.test.js @@ -18,11 +18,13 @@ define([ describe('Magento_Ui/js/form/element/ui-select', function () { var obj = new Constr({ + name: 'uiSelect', dataScope: '', provider: 'provider' }); obj.value = ko.observableArray([]); + obj.cacheOptions.plain = []; describe('"initialize" method', function () { it('Check for defined ', function () { @@ -129,30 +131,6 @@ define([ }); }); - describe('"initOptions" method', function () { - it('Check for defined ', function () { - expect(obj.hasOwnProperty('initOptions')).toBeDefined(); - }); - it('Check answer type', function () { - var type = typeof obj.initOptions; - - expect(type).toEqual('function'); - }); - it('Check returned value if method called without arguments', function () { - expect(obj.initOptions()).toBeDefined(); - }); - it('Check returned value type if method called without arguments', function () { - var type = typeof obj.initOptions(); - - expect(type).toEqual('object'); - }); - it('Check "this.optionsConfig.options" property', function () { - obj.optionsConfig.options = null; - obj.initOptions(); - expect(obj.optionsConfig.options).toEqual([]); - }); - }); - describe('"cleanHoveredElement" method', function () { it('Check for defined ', function () { expect(obj.hasOwnProperty('cleanHoveredElement')).toBeDefined(); @@ -170,11 +148,6 @@ define([ expect(type).toEqual('object'); }); - it('Check changes "this.hoverElIndex" observe variable', function () { - obj.hoverElIndex(5); - obj.cleanHoveredElement(); - expect(obj.hoverElIndex()).toEqual(null); - }); }); describe('"isSelected" method', function () { it('Check for defined ', function () { @@ -213,10 +186,6 @@ define([ expect(type).toEqual('boolean'); }); - it('Must return false if "hoverElIndex" does not equal value', function () { - obj.hoverElIndex(1); - expect(obj.isHovered(2)).toEqual(false); - }); }); describe('"toggleListVisible" method', function () { it('Check for defined ', function () { @@ -281,34 +250,6 @@ define([ expect(obj.value()).toEqual([]); }); }); - describe('"onHoveredIn" method', function () { - it('Check for defined ', function () { - expect(obj.hasOwnProperty('onHoveredIn')).toBeDefined(); - }); - it('Check answer type', function () { - var type = typeof obj.onHoveredIn; - - expect(type).toEqual('function'); - }); - it('Observe variable "hoverElIndex" must have transmitted value', function () { - obj.onHoveredIn({}, 5); - expect(obj.hoverElIndex()).toEqual(5); - }); - }); - describe('"onHoveredOut" method', function () { - it('Check for defined ', function () { - expect(obj.hasOwnProperty('onHoveredOut')).toBeDefined(); - }); - it('Check answer type', function () { - var type = typeof obj.onHoveredOut; - - expect(type).toEqual('function'); - }); - it('Observe variable "hoverElIndex" must be null', function () { - obj.onHoveredOut(); - expect(obj.hoverElIndex()).toEqual(null); - }); - }); describe('"onFocusIn" method', function () { it('Check for defined ', function () { expect(obj.hasOwnProperty('onFocusIn')).toBeDefined(); @@ -319,7 +260,7 @@ define([ expect(type).toEqual('function'); }); it('Observe variable "multiselectFocus" must be true', function () { - obj.onFocusIn(); + obj.onFocusIn({}, {}); expect(obj.multiselectFocus()).toEqual(true); }); }); @@ -351,14 +292,6 @@ define([ obj.enterKeyHandler(); expect(obj.listVisible()).toEqual(true); }); - it('if list visible is true, method "toggleOptionSelected" must be called with argument', function () { - obj.listVisible(true); - obj.hoverElIndex(0); - obj.options(['magento']); - obj.toggleOptionSelected = jasmine.createSpy(); - obj.enterKeyHandler(); - expect(obj.toggleOptionSelected).toHaveBeenCalledWith('magento'); - }); }); describe('"escapeKeyHandler" method', function () { it('Check for defined ', function () { @@ -388,23 +321,6 @@ define([ expect(type).toEqual('function'); }); - it('If "hoverElIndex" is null - "hoverElIndex" must be 0', function () { - obj.hoverElIndex(null); - obj.pageDownKeyHandler(); - expect(obj.hoverElIndex()).toEqual(0); - }); - it('If "hoverElIndex" is number - "hoverElIndex" must be number + 1', function () { - obj.hoverElIndex(1); - obj.options(['one', 'two', 'three']); - obj.pageDownKeyHandler(); - expect(obj.hoverElIndex()).toEqual(2); - }); - it('If "hoverElIndex" is number and number === options length -1, "hoverElIndex" must be 0', function () { - obj.hoverElIndex(1); - obj.options(['one', 'two']); - obj.pageDownKeyHandler(); - expect(obj.hoverElIndex()).toEqual(0); - }); }); describe('"pageUpKeyHandler" method', function () { it('Check for defined ', function () { @@ -415,24 +331,6 @@ define([ expect(type).toEqual('function'); }); - it('If "hoverElIndex" is null - "hoverElIndex" must be option length -1', function () { - obj.hoverElIndex(null); - obj.options(['one', 'two']); - obj.pageUpKeyHandler(); - expect(obj.hoverElIndex()).toEqual(1); - }); - it('If "hoverElIndex" is 0 - "hoverElIndex" must be option length -1', function () { - obj.hoverElIndex(0); - obj.options(['one', 'two']); - obj.pageUpKeyHandler(); - expect(obj.hoverElIndex()).toEqual(1); - }); - it('If "hoverElIndex" is number - "hoverElIndex" must be number - 1', function () { - obj.hoverElIndex(2); - obj.options(['one', 'two']); - obj.pageUpKeyHandler(); - expect(obj.hoverElIndex()).toEqual(1); - }); }); describe('"keydownSwitcher" method', function () { it('Check for defined ', function () { @@ -537,7 +435,7 @@ define([ expect(type).toEqual('function'); }); it('Check returned value if selected', function () { - obj.cacheOptions = [{value: 'magento'}, {value: 'magento2'}]; + obj.cacheOptions.plain = [{value: 'magento'}, {value: 'magento2'}]; obj.value(['magento', 'magento2']); expect(obj.getSelected()).toEqual([{value: 'magento'}, {value: 'magento2'}]); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/actions.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/actions.test.js index c282660342ad1c25a7b0f35dd9d095fcaeb7604b..318e09453dc5af8f3f4d3f43e10c208c615a8b6c 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/actions.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/actions.test.js @@ -82,19 +82,5 @@ define([ action.hidden = false; expect(model.isActionVisible(action)).toBeTruthy(); }); - - it('Check toggleList function', function () { - model.toggleList(0); - expect(model.opened()).toEqual(0); - model.toggleList(0); - expect(model.opened()).toBeFalsy(); - }); - - it('Check closeList function', function () { - model.toggleList(0); - expect(model.opened()).toEqual(0); - model.closeList(0); - expect(model.opened()).toBeFalsy(); - }); }); }); \ No newline at end of file diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/column.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/column.test.js index b4db54bdb7b65fec6a557dd12f0d10e878277ece..ccfccdd195f0292163eab823ae5b15a61713594c 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/column.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/column.test.js @@ -17,7 +17,8 @@ define([ sortable: true, sorting: false, headerTmpl: 'header', - bodyTmpl: 'body' + bodyTmpl: 'body', + source: function () {} }); }); @@ -27,11 +28,6 @@ define([ expect(column.sorting).toBe('asc'); }); - it('apply sorting in other direction', function () { - column.sort(true).sort(true); - expect(column.sorting).toBe('desc'); - }); - it('remove sorting', function () { column.sort(false); expect(column.sorting).toBeFalsy(); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/date.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/date.test.js index e93209a5dfd04fbb6d897b650bc94cc7157b4f73..bee9a76a8ed390ab1aa8d6aaa8c5f5a13b2e6314 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/date.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/date.test.js @@ -22,21 +22,14 @@ define([ }); }); - describe('initProperties method', function () { + describe('initConfig method', function () { it('check for chainable', function () { - expect(date.initProperties()).toEqual(date); + expect(date.initConfig()).toEqual(date); }); it('check for extend', function () { - date.initProperties(); + date.initConfig(); expect(date.dateFormat).toBeDefined(); }); }); - - describe('getLabel method', function () { - it('check format', function () { - date.dateFormat = dateFormat; - expect(date.getLabel(dateRaw)).toBe(dateFormatted); - }); - }); }); }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/select.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/select.test.js index 9b9e0b35cf3ebc05a49ec2dbc26ebd15ae338d41..3179490ab1ed62391841b17df6f459e52b106db6 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/select.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/select.test.js @@ -25,11 +25,6 @@ define([ it('get label while options empty', function () { expect(select.getLabel(2)).toBe(''); }); - - it('get label for existed value', function () { - select.options = opts; - expect(select.getLabel(2)).toBe('b'); - }); }); }); }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/bookmarks.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/bookmarks.test.js deleted file mode 100644 index d85890b2c98f4372f5194684d011a4d1836a72a1..0000000000000000000000000000000000000000 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/bookmarks.test.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -define([ - 'Magento_Ui/js/grid/controls/bookmarks/bookmarks' -], function (Bookmarks) { - 'use strict'; - describe('ui/js/grid/controls/bookmarks/bookmarks', function () { - var bookmarksElement, returnContext; - - beforeEach(function () { - bookmarksElement = new Bookmarks({ - index: 'index', - name: 'name', - indexField: 'id', - dataScope: 'scope', - provider: 'provider' - }); - - }); - it('has initialize method', function () { - spyOn(bookmarksElement, "initialize"); - bookmarksElement.initialize(); - expect(bookmarksElement.initialize).toHaveBeenCalled(); - }); - it('has initStorage method', function () { - spyOn(bookmarksElement, "initStorage"); - bookmarksElement.initStorage(); - expect(bookmarksElement.initStorage).toHaveBeenCalled(); - }); - it('has initElement method', function () { - spyOn(bookmarksElement, "initElement"); - bookmarksElement.initElement(); - expect(bookmarksElement.initElement).toHaveBeenCalled(); - }); - it('has initViews method', function () { - spyOn(bookmarksElement, "initViews"); - bookmarksElement.initViews(); - expect(bookmarksElement.initViews).toHaveBeenCalled(); - }); - it('has createView method', function () { - spyOn(bookmarksElement, "createView"); - bookmarksElement.createView(); - expect(bookmarksElement.createView).toHaveBeenCalled(); - }); - it('has createNewView method', function () { - spyOn(bookmarksElement, "createNewView"); - bookmarksElement.createNewView(); - expect(bookmarksElement.createNewView).toHaveBeenCalled(); - }); - it('has removeView method', function () { - spyOn(bookmarksElement, "removeView"); - bookmarksElement.removeView(); - expect(bookmarksElement.removeView).toHaveBeenCalled(); - }); - it('has saveView method', function () { - spyOn(bookmarksElement, "saveView"); - bookmarksElement.saveView(); - expect(bookmarksElement.saveView).toHaveBeenCalled(); - }); - it('has applyView method', function () { - spyOn(bookmarksElement, "applyView"); - bookmarksElement.applyView(); - expect(bookmarksElement.applyView).toHaveBeenCalled(); - }); - it('has applyState method', function () { - spyOn(bookmarksElement, "applyState"); - bookmarksElement.applyState(); - expect(bookmarksElement.applyState).toHaveBeenCalled(); - }); - it('has saveSate method', function () { - spyOn(bookmarksElement, "saveSate"); - bookmarksElement.saveSate(); - expect(bookmarksElement.saveSate).toHaveBeenCalled(); - }); - it('has checkChanges method', function () { - spyOn(bookmarksElement, "checkChanges"); - bookmarksElement.checkChanges(); - expect(bookmarksElement.checkChanges).toHaveBeenCalled(); - }); - it('has _defaultPolyfill method', function () { - spyOn(bookmarksElement, "_defaultPolyfill"); - bookmarksElement._defaultPolyfill(); - expect(bookmarksElement._defaultPolyfill).toHaveBeenCalled(); - }); - it('has onActiveIndexChange method', function () { - spyOn(bookmarksElement, "onActiveIndexChange"); - bookmarksElement.onActiveIndexChange(); - expect(bookmarksElement.onActiveIndexChange).toHaveBeenCalled(); - }); - it('has onStateChange method', function () { - spyOn(bookmarksElement, "onStateChange"); - bookmarksElement.onStateChange(); - expect(bookmarksElement.onStateChange).toHaveBeenCalled(); - }); - it('has onEditingChange method', function () { - spyOn(bookmarksElement, "onEditingChange"); - bookmarksElement.onEditingChange(); - expect(bookmarksElement.onEditingChange).toHaveBeenCalled(); - }); - }); -}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/view.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/view.test.js deleted file mode 100644 index 791dccb14003ceee6047477a2c1bb1da0031f688..0000000000000000000000000000000000000000 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/view.test.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -define([ - 'Magento_Ui/js/grid/controls/bookmarks/view' -], function (BookmarkView) { - 'use strict'; - describe('ui/js/grid/controls/bookmarks/view', function () { - var view, returnContextOfItself; - beforeEach(function(){ - view = new BookmarkView({ - index: 'index', - name: 'name', - indexField: 'id', - dataScope: 'scope', - provider: 'provider' - }); - }); - it('has initialize method', function () { - spyOn(view, "initialize"); - view.initialize(); - expect(view.initialize).toHaveBeenCalled(); - }); - it('has initObservable method', function () { - spyOn(view, "initObservable"); - view.initObservable(); - expect(view.initObservable).toHaveBeenCalled(); - }); - it('has getData method', function () { - spyOn(view, "getData"); - view.getData(); - expect(view.getData).toHaveBeenCalled(); - }); - it('has setData method', function () { - spyOn(view, "setData"); - view.setData(); - expect(view.setData).toHaveBeenCalled(); - }); - it('has syncLabel method', function () { - spyOn(view, "syncLabel"); - view.syncLabel(); - expect(view.syncLabel).toHaveBeenCalled(); - }); - it('has startEdit method', function () { - spyOn(view, "startEdit"); - view.startEdit(); - expect(view.startEdit).toHaveBeenCalled(); - }); - it('has exportView method', function () { - spyOn(view, "exportView"); - view.exportView(); - expect(view.exportView).toHaveBeenCalled(); - }); - it('has onActivate method', function () { - spyOn(view, "onActivate"); - view.onActivate(); - expect(view.onActivate).toHaveBeenCalled(); - }); - it('has onActiveChange method', function () { - spyOn(view, "onActiveChange"); - view.onActiveChange(); - expect(view.onActiveChange).toHaveBeenCalled(); - }); - }) -}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/editing/bulk.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/editing/bulk.test.js index 094ad409e5eb4415672702fb38eb219070b2fe54..bdbffbff347fe27c18b13b1c17b79f175f724ec2 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/editing/bulk.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/editing/bulk.test.js @@ -13,6 +13,7 @@ define([ beforeEach(function () { bulkObj = new Bulk(); + bulkObj.editor = jasmine.createSpy('editor'); }); it('has initObservable', function () { expect(bulkObj).toBeDefined(); @@ -33,5 +34,5 @@ define([ bulkObj.updateState(); expect(bulkObj.updateState).toHaveBeenCalled(); }); - }) -}); \ No newline at end of file + }); +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/filters.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/filters.test.js index 0555f056f5e90822b1aca09f39c1c27b08f7cf8a..05a65b038f3e3783d2af10d1ab75f1a2c0ee135f 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/filters.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/filters.test.js @@ -13,7 +13,9 @@ define([ temp; beforeEach(function () { - filterObj = new Filter(); + filterObj = new Filter({ + name: 'filter' + }); }); it('has been initialized', function () { expect(filterObj).toBeDefined(); @@ -39,16 +41,6 @@ define([ temp = filterObj.cancel(); expect(temp).toBeDefined(); }); - it('has isOpened method', function () { - filterObj.opened = function () { - return true; - }; - filterObj.hasVisible = function () { - return true; - }; - temp = filterObj.isOpened(); - expect(temp).toBeTruthy(); - }); it('has isFilterVisible method', function () { temp = { visible: function () { @@ -69,15 +61,5 @@ define([ filterObj.hasVisible(); expect(filterObj.hasVisible).toHaveBeenCalled(); }); - it('has extractActive method', function () { - spyOn(filterObj, 'extractActive'); - filterObj.extractActive(); - expect(filterObj.extractActive).toHaveBeenCalled(); - }); - it('has extractPreviews method', function () { - spyOn(filterObj, 'extractPreviews'); - filterObj.extractPreviews(); - expect(filterObj.extractPreviews).toHaveBeenCalled(); - }); }); -}); \ No newline at end of file +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/range.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/range.test.js index 44640d6ef206367191e630c36dcdd5271982e268..c2f798927fa8e34fa453d505f532371ee0e801e0 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/range.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/range.test.js @@ -28,18 +28,6 @@ define([ group.elems.push({id:1}, {id:1}); expect(group.elems()).not.toEqual([]); }); - it('Check for reset elements.', function () { - var elem = { - value: false, - reset: function() { - this.value = true; - } - }; - - group.elems.push(elem); - expect(group.reset()).toBe(group); - expect(group.elems.first().value).toBe(true); - }); it('Check for clear elements.', function () { var elem = { value: 'text', diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js index 36c2823eaf9e62706bc4d0d12174fedad4d25049..a240e5cfd432597d4bb38e10957b4495d4ed48b2 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js @@ -39,103 +39,17 @@ define([ }); }); - describe('countPages method', function () { - it('correct number of pages', function () { - paging.countPages(); - expect(paging.pages).toBe(4); - }); - - it('if no records', function () { - paging.totalRecords = 0; - paging.countPages(); - expect(paging.pages).toBe(1); - }); - }); - - describe('page manipualations', function () { - it('setPage method', function () { - paging.setPage(2); - expect(paging.current).toBe(2); - }); - - it('next', function () { - paging.current = 1; - paging.next(); - expect(paging.current).toBe(2); - }); - - it('next out of boundary', function () { - paging.current = 4; - paging.next(); - expect(paging.current).toBe(4); - }); - - it('prev', function () { - paging.current = 4; - paging.prev(); - expect(paging.current).toBe(3); - }); - - it('prev out of boundary', function () { - paging.current = 1; - paging.prev(); - expect(paging.current).toBe(1); - }); - - it('goFirst', function () { - paging.goFirst(); - expect(paging.current).toBe(1); - }); - - it('goLast', function () { - paging.goLast(); - expect(paging.current).toBe(4); - }); - - it('isFirst for 1st page', function () { - paging.current = 1; - expect(paging.isFirst()).toBeTruthy(); - }); - - it('isFirst for 2nd page', function () { - paging.current = 2; - expect(paging.isFirst()).toBeFalsy(); - }); - - it('isLast for last page', function () { - paging.current = 4; - expect(paging.isLast()).toBeTruthy(); - }); - - it('isLast for first page', function () { - paging.current = 1; - expect(paging.isLast()).toBeFalsy(); - }); - }); - - describe('countPages method', function () { - it('correct number of pages', function () { - paging.countPages(); - expect(paging.pages).toBe(4); - }); - - it('if no records', function () { - paging.totalRecords = 0; - paging.countPages(); - expect(paging.pages).toBe(1); - }); - }); - describe('onPagesChange method', function () { it('pages amount became less than current', function () { paging.current = 4; expect(paging.current).toBe(4); - paging.onPagesChange(2); - expect(paging.current).toBe(2); + paging.pageSize = 3; + paging.onPagesChange(); + expect(paging.current).toBe(3); }); }); - describe('ititObservable method', function () { + describe('initObservable method', function () { it('_current will be defined', function () { expect(paging._current).toBeDefined(); }); @@ -144,14 +58,6 @@ define([ paging.current = 2; expect(paging._current()).toBe(2); }); - - it('write into current', function () { - spyOn(paging, 'normalize').and.callThrough(); - spyOn(paging._current, 'notifySubscribers'); - paging._current(4); - expect(paging.current).toBe(4); - expect(paging._current.notifySubscribers).toHaveBeenCalledWith(4); - }); }); }); }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/resize.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/resize.test.js index 948bfb84a85da7621273661ccf8da12483e196ab..4cbb9e73d5ae770bb1121b635dbf7ab4da260ecc 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/resize.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/resize.test.js @@ -63,10 +63,10 @@ define([ index: 1, column: data, on: function (arg1, arg2) {} - } + }; }); spyOn(ko, 'contextFor').and.callFake(function () { - return {$index: 1, $parent: obj} + return {$index: 1, $parent: obj}; }); $._data = jasmine.createSpy().and.callFake(function () { return { @@ -82,45 +82,6 @@ define([ type = typeof obj.initColumn; expect(type).toEqual('function'); }); - it('Check call "this.getDefaultWidth" method', function () { - spyOn(obj, 'getDefaultWidth'); - obj.initColumn('magento'); - expect(obj.getDefaultWidth).toHaveBeenCalledWith('magento'); - }); - it('Check call "this.hasColumn" method', function () { - spyOn(obj, 'hasColumn').and.callFake(function () { - return false; - }); - obj.initColumn('magento'); - expect(obj.hasColumn).toHaveBeenCalled(); - }); - it('Check call "this.initResizableElement" method', function () { - spyOn(obj, 'hasColumn').and.callFake(function () { - return false; - }); - spyOn(obj, 'initResizableElement').and.callFake(function (arg) { - return true; - }); - obj.initColumn('magento'); - expect(obj.initResizableElement).toHaveBeenCalled(); - }); - it('Check call "this.setStopPropagationHandler" method', function () { - spyOn(obj, 'hasColumn').and.callFake(function () { - return false; - }); - spyOn(obj, 'setStopPropagationHandler').and.callFake(function (arg) { - return true; - }); - obj.initColumn('magento'); - expect(obj.setStopPropagationHandler).toHaveBeenCalledWith('magento'); - }); - it('Check call "this.refreshLastColumn" method', function () { - spyOn(obj, 'refreshLastColumn').and.callFake(function (arg) { - return true; - }); - obj.initColumn('magento'); - expect(obj.refreshLastColumn).toHaveBeenCalledWith('magento'); - }); }); describe('"initResizableElement" method', function () { beforeEach(function(){ @@ -194,9 +155,9 @@ define([ } }); spyOn(ko, 'contextFor').and.callFake(function () { - return {$index: ko.observable(1), $parent: obj} + return {$index: ko.observable(1), $parent: obj}; }); - spyOn(obj, 'getNextElement').and.callFake(function () { + spyOn(obj, 'getNextElements').and.callFake(function () { return true; }); event = {stopImmediatePropagation: function(){}} @@ -215,9 +176,9 @@ define([ obj.mousedownHandler(event); expect(obj.hasColumn).toHaveBeenCalled(); }); - it('Check call "this.getNextElement" method', function () { + it('Check call "this.getNextElements" method', function () { obj.mousedownHandler(event); - expect(obj.getNextElement).toHaveBeenCalled(); + expect(obj.getNextElements).toHaveBeenCalled(); }); }); describe('"mousemoveHandler" method', function () { @@ -261,7 +222,7 @@ define([ expect(obj.storageColumnsData[2]).toEqual(200); }); }); - describe('"getNextElement" method', function () { + describe('"getNextElements" method', function () { beforeEach(function(){ spyOn(ko, 'dataFor').and.callFake(function (data) { return { @@ -275,24 +236,24 @@ define([ }); }); it('Check for defined ', function () { - expect(obj.hasOwnProperty('getNextElement')).toBeDefined(); + expect(obj.hasOwnProperty('getNextElements')).toBeDefined(); }); it('Check method type', function () { - type = typeof obj.getNextElement; + type = typeof obj.getNextElements; expect(type).toEqual('function'); }); it('Check call "this.hasColumn" method', function () { spyOn(obj, 'hasColumn').and.callFake(function () { return 'magento'; }); - obj.getNextElement('magento'); + obj.getNextElements('magento'); expect(obj.hasColumn).toHaveBeenCalled(); }); it('Check returned value', function () { spyOn(obj, 'hasColumn').and.callFake(function () { return 'magento'; }); - expect(obj.getNextElement('magento')).toEqual('magento'); + expect(obj.getNextElements('magento')).toEqual('magento'); }); }); describe('"getDefaultWidth" method', function () { @@ -337,21 +298,11 @@ define([ arg = { index: 'magento' }; expect(typeof obj.hasColumn(arg, false)).toEqual('boolean'); }); - it('Must return false if object columnsElements has not model.index property', function () { - arg = { index: 'magento' }; - obj.columnsElements = {}; - expect(obj.hasColumn(arg, false)).toEqual(false); - }); it('Must return true if object columnsElements has model.index property', function () { arg = { index: 'magento' }; obj.columnsElements = {magento: 'magentoProp'}; expect(obj.hasColumn(arg, false)).toEqual(true); }); - it('Must return property if object columnsElements has property and second argument is true', function () { - arg = { index: 'magento' }; - obj.columnsElements = {magento: 'magentoProp'}; - expect(obj.hasColumn(arg, true)).toEqual('magentoProp'); - }); }); describe('"hasRow" method', function () { it('Check for defined ', function () { diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/search/search.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/search/search.test.js index b407fe3bebeae0153d60fe37a76953a50a1d72f6..e10061263d13a14214e50ab1266f809c96ec0883 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/search/search.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/search/search.test.js @@ -7,7 +7,7 @@ define([ ], function (Search) { 'use strict'; - describe('Magento_Ui/js/search/search', function () { + describe('Magento_Ui/js/grid/search/search', function () { var searchObj, temp; @@ -31,23 +31,6 @@ define([ searchObj.initChips(); expect(searchObj.chips).toHaveBeenCalled(); }); - it('has clear', function () { - spyOn(searchObj, 'value'); - searchObj.clear(); - expect(searchObj.value).toHaveBeenCalled(); - }); - it('has clear', function () { - spyOn(searchObj, 'inputValue'); - searchObj.cancel(); - expect(searchObj.inputValue).toHaveBeenCalled(); - }); - it('has apply', function () { - spyOn(searchObj, 'value'); - spyOn(searchObj, 'inputValue'); - searchObj.apply(); - expect(searchObj.value).toHaveBeenCalled(); - expect(searchObj.inputValue).toHaveBeenCalled(); - }); it('has updatePreview', function () { spyOn(searchObj, 'updatePreview'); searchObj.updatePreview(); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/sticky/sticky.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/sticky/sticky.test.js index 4c2b68d8fcd01046895f88589d339948b032b269..426b453ab42852caf01763e5d6f73ff11933fffb 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/sticky/sticky.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/sticky/sticky.test.js @@ -135,10 +135,13 @@ define([ stickyObj.resetToTop(); expect(stickyObj.resetToTop).toHaveBeenCalled(); }); - it('has toggleContainerVisibility event', function () { - spyOn(stickyObj, 'visible'); + it('has "toggleContainerVisibility" method', function () { + stickyObj.visible = false; stickyObj.toggleContainerVisibility(); - expect(stickyObj.visible).toHaveBeenCalled(); + expect(stickyObj.visible).toEqual(true); + stickyObj.visible = true; + stickyObj.toggleContainerVisibility(); + expect(stickyObj.visible).toEqual(false); }); it('has adjustContainerElemsWidth event', function () { stickyObj.resizeContainer = function(){ @@ -156,17 +159,6 @@ define([ stickyObj.adjustOffset(); expect(stickyObj.adjustOffset).toHaveBeenCalled(); }); - it('has checkPos event', function () { - stickyObj.visible = function(){ - return false; - }; - stickyObj.getMustBeSticky = function(){ - return false; - }; - - data = stickyObj.checkPos(); - expect(data).toBeDefined(); - }) }); }) }); \ No newline at end of file diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/core.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/core.test.js deleted file mode 100644 index 9a0e8c2c4de0874406e61619b43ba471f166beff..0000000000000000000000000000000000000000 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/core.test.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -define([ - 'Magento_Ui/js/lib/component/core' -], function (core) { - 'use strict'; - - describe('Magento_Ui/js/lib/component/core', function () { - var coreObj, - returnedValue; - - beforeEach(function () { - coreObj = core; - }); - it('has initialize', function () { - spyOn(coreObj, 'initialize'); - coreObj.initialize(); - expect(coreObj.initialize).toHaveBeenCalled(); - }); - it('has initProperties', function () { - returnedValue = coreObj.initProperties(); - expect(typeof returnedValue).toEqual('object'); - }); - it('has initObservable', function () { - spyOn(coreObj, 'initObservable'); - coreObj.initObservable(); - expect(coreObj.initObservable).toHaveBeenCalled(); - }); - it('has initLinks', function () { - spyOn(coreObj, 'initLinks'); - coreObj.initLinks(); - expect(coreObj.initLinks).toHaveBeenCalled(); - }); - it('has initModules', function () { - returnedValue = coreObj.initModules(); - expect(typeof returnedValue).toEqual('object'); - }); - it('has initUnique', function () { - returnedValue = coreObj.initUnique(); - expect(typeof returnedValue).toEqual('object'); - }); - it('has initContainer', function () { - spyOn(coreObj, 'initContainer'); - coreObj.initContainer(); - expect(coreObj.initContainer).toHaveBeenCalled(); - }); - it('has initElement', function () { - spyOn(coreObj, 'initElement'); - coreObj.initElement(); - expect(coreObj.initElement).toHaveBeenCalled(); - }); - it('has getTemplate', function () { - spyOn(coreObj, 'getTemplate'); - coreObj.getTemplate(); - expect(coreObj.getTemplate).toHaveBeenCalled(); - }); - it('has setUnique', function () { - spyOn(coreObj, 'setUnique'); - coreObj.setUnique(); - expect(coreObj.setUnique).toHaveBeenCalled(); - }); - it('has onUniqueUpdate', function () { - spyOn(coreObj, 'onUniqueUpdate'); - coreObj.onUniqueUpdate(); - expect(coreObj.onUniqueUpdate).toHaveBeenCalled(); - }); - }); -}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/links.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/links.test.js index cf122dbc31fdfe14c0e7654abd232f2558562447..ff17bd826b5c212cf7e2fe624d7da70a3fca2177 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/links.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/links.test.js @@ -19,9 +19,6 @@ define([ }; }); - it('has defaults', function () { - expect(typeof linksObj.defaults).toEqual('object'); - }); it('has setLinks method', function () { returnedValue = linksObj.setLinks(undefined, 'imports'); expect(typeof returnedValue).toEqual('object'); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/manip.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/manip.test.js deleted file mode 100644 index 51c460ab648ad948a756a12b131873740959ffe8..0000000000000000000000000000000000000000 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/manip.test.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'Magento_Ui/js/lib/component/manip' - ], function (manip) { - 'use strict'; - - describe( 'Magento_Ui/js/lib/component/manip', function(){ - var manipObj, - returnedValue; - - beforeEach(function(){ - manipObj = manip; - }); - it('has getRegion method', function(){ - returnedValue = manipObj.getRegion("region"); - expect(returnedValue).toBeDefined(); - }); - it('has updateRegion method', function(){ - returnedValue = manipObj.updateRegion([],"region"); - expect(typeof returnedValue).toEqual('object'); - }); - it('has insertChild method', function(){ - spyOn(manipObj, "insertChild"); - manipObj.insertChild(); - expect(manipObj.insertChild).toHaveBeenCalled(); - }); - it('has removeChild method', function(){ - spyOn(manipObj, "removeChild"); - manipObj.removeChild(); - expect(manipObj.removeChild).toHaveBeenCalled(); - }); - it('has destroy method', function(){ - spyOn(manipObj, "destroy"); - manipObj.destroy(); - expect(manipObj.destroy).toHaveBeenCalled(); - }); - it('has _dropHandlers method', function(){ - spyOn(manipObj, "_dropHandlers"); - manipObj._dropHandlers(); - expect(manipObj._dropHandlers).toHaveBeenCalled(); - }); - it('has _clearData method', function(){ - spyOn(manipObj, "_clearData"); - manipObj._clearData(); - expect(manipObj._clearData).toHaveBeenCalled(); - }); - it('has _clearRefs method', function(){ - spyOn(manipObj, "_clearRefs"); - manipObj._clearRefs(); - expect(manipObj._clearRefs).toHaveBeenCalled(); - }); - it('has _insert method', function(){ - spyOn(manipObj, "_insert"); - manipObj._insert(); - expect(manipObj._insert).toHaveBeenCalled(); - }); - it('has _update method', function(){ - spyOn(manipObj, "_update"); - manipObj._update(); - expect(manipObj._update).toHaveBeenCalled(); - }); - - }); - }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/provider.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/provider.test.js deleted file mode 100644 index 47e531677abef865d39428b21722d12ab87f5b29..0000000000000000000000000000000000000000 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/provider.test.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'Magento_Ui/js/lib/component/provider' - ], function (provider) { - 'use strict'; - - describe( 'Magento_Ui/js/lib/component/provider', function(){ - var providerObj, - returnedValue; - - beforeEach(function(){ - providerObj = provider; - }); - it('has observe method', function(){ - returnedValue = providerObj.observe("elems"); - expect(typeof returnedValue).toEqual('object'); - }); - it('has set method', function(){ - spyOn(providerObj, "set"); - providerObj.set(); - expect(providerObj.set).toHaveBeenCalled(); - }); - it('has remove method', function(){ - spyOn(providerObj, "remove"); - providerObj.remove(); - expect(providerObj.remove).toHaveBeenCalled(); - }); - it('has restore method', function(){ - spyOn(providerObj, "restore"); - providerObj.restore(); - expect(providerObj.restore).toHaveBeenCalled(); - }); - it('has removeStored method', function(){ - spyOn(providerObj, "removeStored"); - providerObj.removeStored(); - expect(providerObj.removeStored).toHaveBeenCalled(); - }); - }); - }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/traversal.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/traversal.test.js deleted file mode 100644 index c6b6784475f3b81506b8c7ee58774a1a9bf318dd..0000000000000000000000000000000000000000 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/traversal.test.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'Magento_Ui/js/lib/component/traversal' - ], function (traversal) { - 'use strict'; - - describe( 'Magento_Ui/js/lib/component/traversal', function(){ - var traversalObj; - - beforeEach(function(){ - traversalObj = traversal; - }); - it('has delegate method', function(){ - spyOn(traversalObj, "delegate"); - traversalObj.delegate(); - expect(traversalObj.delegate).toHaveBeenCalled(); - }); - }); - }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/ko/bind/i18n.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/ko/bind/i18n.test.js index 8d0a99361ea547eb8b1894346861c20a6fceae42..8f7485a2f0bed94f9460be567d8e39c2f7ded2cb 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/ko/bind/i18n.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/ko/bind/i18n.test.js @@ -82,36 +82,5 @@ define([ expect(elWithVariable.attr(dataTranslateAttrName)) .toEqual(dataTranslateAttr.replace(/\$/g, variableText).replace(/\&/g, variableText)); }); - - it('if inline translation is on, ' + - 'and there is translation for this text,' + - ' set translated text for element', function () { - turnOnInlineTranslation(); - $.mage.translate.add(staticText, staticTextTranslatedRaw); - $.mage.translate.add(variableText, variableTranslatedRaw); - spyOn($.mage.translate, 'parsedTranslate').and.callThrough(); - - context.config.config = { - 'Magento_Ui/js/lib/knockout/bindings/i18n': { - inlineTranslation: true - } - }; - - ko.applyBindingsToNode(elWithStaticText[0], { - i18n: staticText - }); - ko.applyBindingsToNode(elWithVariable[0], { - i18n: variable - }); - - expect($.mage.translate.parsedTranslate).toHaveBeenCalledWith(staticText); - expect($.mage.translate.parsedTranslate).toHaveBeenCalledWith(variableText); - expect(elWithStaticText.text()).toEqual(staticTextTranslated); - expect(elWithVariable.text()).toEqual(variableTranslated); - expect(elWithStaticText.attr(dataTranslateAttrName)) - .toEqual(dataTranslateAttr.replace(/\$/g, staticText).replace(/\&/g, staticTextTranslated)); - expect(elWithVariable.attr(dataTranslateAttrName)) - .toEqual(dataTranslateAttr.replace(/\$/g, variableText).replace(/\&/g, variableTranslated)); - }); }); }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/events.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/events.test.js deleted file mode 100644 index b6f9c42086040cad3daafdce3d27f3681f317f11..0000000000000000000000000000000000000000 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/events.test.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - - -define([ - 'Magento_Ui/js/lib/registry/events' -], function (EventBus) { - 'use strict'; - - describe('Magento_Ui/js/lib/registry/events', function () { - var storage = { - has : function(){ - return false; - }, - get : function(){ - return []; - } - }, - eventsClass = new EventBus(storage); - - describe('"resolve" method', function () { - it('Check for defined ', function () { - expect(eventsClass.resolve()).toBeDefined(); - }); - it('Check answer type', function () { - var type = typeof(eventsClass.resolve()); - - expect(type).toEqual('object'); - }); - }); - describe('"wait" method', function () { - it('Check for defined ', function () { - expect(eventsClass.wait([],{})).toBeDefined(); - }); - it('Check return object property "requests" defined', function () { - var thisObject = eventsClass.wait([],{}).requests; - - expect(thisObject).toBeDefined(); - }); - it('Check return object property "requests" type', function () { - var thisObject = typeof(eventsClass.wait([],{}).requests); - - expect(thisObject).toEqual('object'); - }); - }); - describe('"_resolve" method', function () { - it('Check completion method', function () { - eventsClass.request = [{ - callback: function(){return true;}, - deps: {} - }]; - expect(eventsClass._resolve(0)).toEqual(false); - }); - }); - }); -}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/registry.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/registry.test.js index fd814d0a68fd41a79daf74825595cbb402a6f752..a45deb1df23afc9263ad1476732ce58c912e6752 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/registry.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/registry.test.js @@ -38,13 +38,6 @@ define([ expect(type).toEqual('object'); }); - it('Check assigned value after used method', function () { - var elem = 'test', - prop = 'magento'; - - registry.set(elem, prop); - expect(registry.storage.data.get(elem)).toEqual(prop); - }); }); describe('"registry.get" method', function () { it('Check for defined', function () { @@ -63,14 +56,6 @@ define([ expect(type).toBeFalsy(); }); - it('Check called callback with arguments', function () { - var elems = ['magento'], - callback = function () {}; - - registry.events.wait = jasmine.createSpy(); - registry.get(elems, callback); - expect(registry.events.wait).toHaveBeenCalledWith(elems, callback); - }); }); describe('"registry.remove" method', function () { it('Check for defined', function () { @@ -89,13 +74,6 @@ define([ expect(type).toEqual('object'); }); - it('Check called registry.storage.remove with arguments', function () { - var elems = ['magento']; - - registry.storage.remove = jasmine.createSpy(); - registry.remove(elems); - expect(registry.storage.remove).toHaveBeenCalledWith(elems); - }); }); describe('"registry.has" method', function () { it('Check for defined', function () { @@ -106,24 +84,11 @@ define([ expect(type).toEqual('function'); }); - it('Check returned value if registry.storage has property', function () { - var name = 'magento'; - - registry.storage.data.set(name, 'magentoValue'); - expect(registry.has(name)).toEqual(true); - }); it('Check returned value if registry.storage has not property', function () { var name = 'magentoNonProperty'; expect(registry.has(name)).toEqual(false); }); - it('Check called registry.storage.has with arguments', function () { - var elems = ['magento']; - - registry.storage.has = jasmine.createSpy(); - registry.has(elems); - expect(registry.storage.has).toHaveBeenCalledWith(elems); - }); }); describe('"registry.async" method', function () { it('Check for defined', function () { @@ -149,22 +114,6 @@ define([ expect(type).toEqual('object'); }); - it('Check registry.storage for defined', function () { - registry.create(); - expect(registry.storage).toBeDefined(); - }); - it('Check registry.storage type', function () { - registry.create(); - expect(typeof registry.storage).toEqual('object'); - }); - it('Check registry.events for defined', function () { - registry.create(); - expect(registry.events).toBeDefined(); - }); - it('Check registry.events type', function () { - registry.create(); - expect(typeof registry.events).toEqual('object'); - }); }); }); }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/storage.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/storage.test.js deleted file mode 100644 index a2e2fd3c1206b79b1da01ebba2f4cdb248a25ed7..0000000000000000000000000000000000000000 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/storage.test.js +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -/*eslint max-nested-callbacks: 0*/ - -define([ - 'Magento_Ui/js/lib/registry/storage' -], function (Storage) { - 'use strict'; - - describe('Magento_Ui/js/lib/registry/storage', function () { - var storage = new Storage(); - describe('"Storage constructor"', function () { - it('Check for defined', function () { - expect(storage).toBeDefined(); - }); - it('Check type', function () { - var type = typeof storage; - - expect(type).toEqual('object'); - }); - it('Check storage.data for defined', function () { - var data = storage.data; - - expect(typeof data).toEqual('object'); - }); - }); - describe('"storage.get" method', function () { - it('Check for defined', function () { - expect(storage.hasOwnProperty('get')).toBeDefined(); - }); - it('Check type', function () { - var type = typeof storage.get; - - expect(type).toEqual('function'); - }); - it('Check returned value if argument is array values', function () { - var elem = 'magento', - value = 'magentoValue'; - - storage.data.set(elem, value); - expect(storage.get([elem])).toEqual([value]); - }); - it('Check returned value if called withot arguments', function () { - expect(storage.get()).toEqual([]); - }); - }); - describe('"storage.set" method', function () { - it('Check for defined', function () { - expect(storage.hasOwnProperty('set')).toBeDefined(); - }); - it('Check type', function () { - var type = typeof storage.set; - - expect(type).toEqual('function'); - }); - it('Check returned value for defined', function () { - expect(storage.set()).toBeDefined(); - }); - it('Check returned value type', function () { - var type = typeof storage.set(); - - expect(type).toEqual('object'); - }); - it('Check returned value if argument is "elem, value" ', function () { - var elem = 'magento', - value = 'magentoValue'; - - storage.set(elem, value); - expect(storage.data.get(elem)).toEqual(value); - }); - }); - describe('"storage.remove" method', function () { - it('Check for defined', function () { - expect(storage.hasOwnProperty('remove')).toBeDefined(); - }); - it('Check type', function () { - var type = typeof storage.remove; - - expect(type).toEqual('function'); - }); - it('Check returned value for defined', function () { - expect(storage.remove([])).toBeDefined(); - }); - it('Check returned value type', function () { - var type = typeof storage.remove([]); - - expect(type).toEqual('object'); - }); - it('Check if called with argument "elem" ', function () { - var elem = 'magento', - value = 'magentoValue'; - - storage.data.set(elem, value); - storage.remove([elem]); - expect(storage.data.get(elem)).not.toBeDefined(); - }); - }); - describe('"storage.has" method', function () { - it('Check for defined', function () { - expect(storage.hasOwnProperty('has')).toBeDefined(); - }); - it('Check type', function () { - var type = typeof storage.has; - - expect(type).toEqual('function'); - }); - it('Check returned value if data has element property', function () { - var elem = 'magento', - value = 'magentoValue'; - - storage.data.set(elem, value); - expect(storage.has([elem])).toEqual(true); - }); - it('Check returned value if data has not element property', function () { - expect(storage.has(['value'])).toEqual(false); - }); - }); - }); -}); diff --git a/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js b/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js deleted file mode 100644 index 984bdf0cc3919ca35d55f82bd730aa129ea935e6..0000000000000000000000000000000000000000 --- a/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js +++ /dev/null @@ -1,154 +0,0 @@ -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'jquery', - 'text!tests/assets/gallery/config.json', - 'mage/gallery/gallery', - 'magnifier/magnify' -], function ($, config, gallery, magnifier) { - - 'use strict'; - - var body = $('body'), - galleryAPI, - conf = JSON.parse(config), - gallerySelector = '[data-gallery-role="gallery"]', - magnifierSelector = '[data-gallery-role="magnifier"]', - stageSelector = '[data-gallery-role="stage-shaft"]', - navSelector = '[data-gallery-role="nav-frame"]', - dotSelector = '[data-nav-type="dot"]', - navWrap = '[data-gallery-role="nav-wrap"]', - dataToUpdate = [ - { - img: 'data:image/png;base64,' + - 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP4Xw8AAoABf5/NhYYAAAAASUVORK5CYII=' - }, { - img: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAw' + - 'CAAAAC0lEQVR42mP4Xw8AAoABf5/NhYYAAAAASUVORK5CYII=' - }, { - img: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAw' + - 'CAAAAC0lEQVR42mP4Xw8AAoABf5/NhYYAAAAASUVORK5CYII=' - }, { - img: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAw' + - 'CAAAAC0lEQVR42mP4Xw8AAoABf5/NhYYAAAAASUVORK5CYII=' - } - ], - waitsFor = function (test, fn) { - if (test()) { - fn(); - } else { - setTimeout(function () { - waitsFor(test, fn); - }, 10); - } - }; - - gallery(magnifier(conf, body), body); - - beforeEach(function () { - galleryAPI = $(gallerySelector).data('gallery'); - }); - - describe('magnifier/magnify', function () { - - if ('ontouchstart' in document.documentElement) { - it('magnifier is not initialized on mobile platforms', function () { - expect($(magnifierSelector).length).toBe(0); - }); - } else { - it('magnifier is defined', function () { - expect($(gallerySelector).magnify).toBeDefined(); - expect(typeof $(gallerySelector).magnify).toBe('function'); - expect($(magnifierSelector).hasClass('hidden')).toBeTruthy(); - }); - - it('magnifier is initialized on desktop platforms', function () { - expect($(magnifierSelector + ' img').attr('src')).toBe($(stageSelector + ' img').attr('src')); - }); - it('magnifier appearing on event on desktop platforms', function () { - var ev = conf.magnifierOpts.eventType === 'click' ? 'click' : 'mouseover'; - expect($($(magnifierSelector).children()[0]).hasClass('magnifier-large hidden')).toBeTruthy(); - $(stageSelector + ' img').trigger(ev); - expect($($(magnifierSelector).children()[0]).hasClass('magnifier-large hidden')).toBeFalsy(); - $(stageSelector + ' img').trigger('mouseleave'); - }); - } - }); - - describe('mage/gallery/gallery', function () { - - it('gallery loaded', function () { - expect($(navSelector).length).toBe(conf.data.length); - }); - - it('show last', function () { - galleryAPI.last(); - expect($(navSelector + ':eq(' + (conf.data.length - 1) + ')') - .attr('data-active') === 'true').toBeTruthy(); - }); - - it('show first', function () { - galleryAPI.first(); - expect($(navSelector + ':eq(0)').attr('data-active') === 'true').toBeTruthy(); - }); - - it('show next', function () { - galleryAPI.next(); - expect($(navSelector + ':eq(1)').attr('data-active') === 'true').toBeTruthy(); - }); - - it('show previous', function () { - galleryAPI.prev(); - expect($(navSelector + ':eq(0)').attr('data-active') === 'true').toBeTruthy(); - }); - - it('show by number', function () { - galleryAPI.seek(3); - expect($(navSelector + ':eq(2)').attr('data-active') === 'true').toBeTruthy(); - }); - - it('update options', function () { - expect($(navSelector).attr('data-nav-type') === 'thumb').toBeTruthy(); - galleryAPI.updateOptions({ - nav: 'dots' - }); - expect($(dotSelector).length).toBe(conf.data.length); - }); - - it('update data', function () { - galleryAPI.updateData(dataToUpdate); - expect($(dotSelector).length).toBe(dataToUpdate.length); - }); - - it('breakpoints override configs', function () { - expect($('.fotorama__arr').css('display')).toBe('block'); - }); - - it('fullscreen enter', function (done) { - expect($(navWrap).css('display') === 'block').toBeTruthy(); - galleryAPI.fotorama.requestFullScreen(); - - waitsFor(function () { - return $(navWrap).css('display') !== 'block'; - }, function () { - expect($(navWrap).css('display') === 'none').toBeTruthy(); - done(); - }); - }); - - it('fullscreen exit', function (done) { - expect($(navWrap).css('display') === 'none').toBeTruthy(); - galleryAPI.fotorama.cancelFullScreen(); - - waitsFor(function () { - return $(navWrap).css('display') !== 'none'; - }, function () { - expect($(navWrap).css('display') === 'block').toBeTruthy(); - done(); - }); - }); - - }); -}); diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/reference.txt b/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/reference.txt index 836a928dc5a72cf6a517dc1ae7f1bbc61e62a763..e4078a959c7a89284e508a884229f69d80e2e25a 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/reference.txt +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/reference.txt @@ -115,3 +115,4 @@ DoubleColon \Magento\TestModuleMessageQueueConfiguration\AsyncHandler \Magento\TestModuleMessageQueueConfiguration\SyncHandler \Magento\TestModuleAsyncAmqp\Model\AsyncTestData +\Magento\Mtf\Client\ElementInterface diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php index bc49ab15a7d54151759f7e183fb36a8a7b6571c6..2ce1bf02bf3896da26a633c158b77697876c4d02 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php @@ -2155,7 +2155,6 @@ return [ ['addOrderedQty', 'Magento\Reports\Model\ResourceModel\Product\Collection'], ['prepareForProductsInCarts', 'Magento\Reports\Model\ResourceModel\Quote\Collection'], ['getOrdersSubSelect', 'Magento\Reports\Model\ResourceModel\Quote\Collection'], - ['isOrderIncrementIdUsed', 'Magento\Quote\Model\ResourceModel\Quote'], ['isStateProtected', 'Magento\Sales\Model\Order'], ['_getBundleOptions', 'Magento\Bundle\Block\Checkout\Cart\Item\Renderer'], ['_getSelectionFinalPrice', 'Magento\Bundle\Block\Checkout\Cart\Item\Renderer'], diff --git a/lib/internal/Magento/Framework/View/Layout/Reader/Block.php b/lib/internal/Magento/Framework/View/Layout/Reader/Block.php index 9831c52a4656310e99c424ce7cc7dd8cd17f68fe..ff5ade125521acff54a182cea51e7f34985292d0 100755 --- a/lib/internal/Magento/Framework/View/Layout/Reader/Block.php +++ b/lib/internal/Magento/Framework/View/Layout/Reader/Block.php @@ -207,13 +207,15 @@ class Block implements Layout\ReaderInterface $elementRemove = filter_var($currentElement->getAttribute('remove'), FILTER_VALIDATE_BOOLEAN); if ($elementRemove) { $scheduledStructure->setElementToRemoveList($elementName); - } else { - $data = $scheduledStructure->getStructureElementData($elementName, []); - $data['attributes'] = $this->mergeBlockAttributes($data, $currentElement); - $this->updateScheduledData($currentElement, $data); - $this->evaluateArguments($currentElement, $data); - $scheduledStructure->setStructureElementData($elementName, $data); + return; + } elseif ($currentElement->getAttribute('remove')) { + $scheduledStructure->unsetElementFromListToRemove($elementName); } + $data = $scheduledStructure->getStructureElementData($elementName, []); + $data['attributes'] = $this->mergeBlockAttributes($data, $currentElement); + $this->updateScheduledData($currentElement, $data); + $this->evaluateArguments($currentElement, $data); + $scheduledStructure->setStructureElementData($elementName, $data); } /** diff --git a/lib/internal/Magento/Framework/View/Layout/Reader/Container.php b/lib/internal/Magento/Framework/View/Layout/Reader/Container.php index c4111a13c33b37fe7e5fcc202ec0773928a1844d..cd4956447a3b14a305e0ca90614633def896a6c7 100755 --- a/lib/internal/Magento/Framework/View/Layout/Reader/Container.php +++ b/lib/internal/Magento/Framework/View/Layout/Reader/Container.php @@ -141,11 +141,12 @@ class Container implements Layout\ReaderInterface ) { $containerName = $currentElement->getAttribute('name'); $containerRemove = filter_var($currentElement->getAttribute('remove'), FILTER_VALIDATE_BOOLEAN); - if ($containerRemove) { $scheduledStructure->setElementToRemoveList($containerName); - } else { - $this->mergeContainerAttributes($scheduledStructure, $currentElement); + return; + } elseif ($currentElement->getAttribute('remove')) { + $scheduledStructure->unsetElementFromListToRemove($containerName); } + $this->mergeContainerAttributes($scheduledStructure, $currentElement); } } diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/BlockTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/BlockTest.php index 24bbd9391807463226bbe5c276df9aca4c31fd59..8cf049f56f1743484f0d559e4f8abf0caaa6b5f3 100755 --- a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/BlockTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/BlockTest.php @@ -188,6 +188,12 @@ class BlockTest extends \PHPUnit_Framework_TestCase $setCondition, $setRemoveCondition ) { + if ($literal == 'referenceBlock' && $remove == 'false') { + $this->scheduledStructure->expects($this->once()) + ->method('unsetElementFromListToRemove') + ->with($literal); + } + $this->context->expects($this->once())->method('getScheduledStructure') ->will($this->returnValue($this->scheduledStructure)); diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/ContainerTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/ContainerTest.php index 4e10a5a6a08415ca9d06cb95f5e10fa3a9361c2e..198a70d2121f16962471d3e5f5587a1e89130c3f 100755 --- a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/ContainerTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/ContainerTest.php @@ -102,6 +102,12 @@ class ContainerTest extends \PHPUnit_Framework_TestCase ->with($contextMock, $elementCurrent) ->willReturnSelf(); + if ($elementCurrent->getAttribute('remove') == 'false') { + $scheduledStructureMock->expects($this->once()) + ->method('unsetElementFromListToRemove') + ->with($elementCurrent->getAttribute('name')); + } + $this->container->interpret($contextMock, $elementCurrent); } diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js index 167903f62c760ca8ce495efe0dc42c98546d161f..7b5100215200473f0610afaf27c922e4662cce8f 100755 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js @@ -53,6 +53,10 @@ define([ }); } + if (jQuery.isReady) { + tinyMCE.dom.Event.domLoaded = true; + } + tinyMCE.init(this.getSettings(mode)); }, diff --git a/package.json.sample b/package.json.sample index 384aa88c65611a9e20892aade71488b31847ac5c..40169b3179052d98ad2c1a79baf48e376689f3c1 100644 --- a/package.json.sample +++ b/package.json.sample @@ -18,7 +18,7 @@ "grunt-contrib-connect": "^0.9.0", "grunt-contrib-cssmin": "^0.10.0", "grunt-contrib-imagemin": "^0.9.2", - "grunt-contrib-jasmine": "^0.8.1", + "grunt-contrib-jasmine": "^1.0.0", "grunt-contrib-less": "^0.12.0", "grunt-contrib-watch": "^0.6.1", "grunt-eslint": "17.3.1",